mirror of
https://github.com/0rangebananaspy/authelia.git
synced 2024-09-14 22:47:21 +07:00
Authentication workflow is complete.
This commit is contained in:
parent
9d7155a969
commit
f61a052bf5
523
client-react/package-lock.json
generated
523
client-react/package-lock.json
generated
|
@ -955,6 +955,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz",
|
||||
"integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ=="
|
||||
},
|
||||
"@types/node-sass": {
|
||||
"version": "3.10.32",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-sass/-/node-sass-3.10.32.tgz",
|
||||
"integrity": "sha1-spbM5xRP+rd7hAkMqtTx5Lvqjgk=",
|
||||
"requires": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/prop-types": {
|
||||
"version": "15.5.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.5.8.tgz",
|
||||
|
@ -1218,6 +1226,11 @@
|
|||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.0.tgz",
|
||||
"integrity": "sha512-sY5AXXVZv4Y1VACTtR11UJCPHHudgY5i26Qj5TypE6DKlIApbwb5uqhXcJ5UUGbvZNRh7EeIoW+LrJumBsKp7w=="
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.5",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
|
||||
|
@ -1297,6 +1310,11 @@
|
|||
"resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
|
||||
"integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM="
|
||||
},
|
||||
"amdefine": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
|
||||
"integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU="
|
||||
},
|
||||
"ansi-colors": {
|
||||
"version": "3.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz",
|
||||
|
@ -1605,6 +1623,15 @@
|
|||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
|
||||
"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz",
|
||||
"integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==",
|
||||
"requires": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
|
@ -1650,6 +1677,11 @@
|
|||
"resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz",
|
||||
"integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw="
|
||||
},
|
||||
"array-find-index": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
|
||||
"integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E="
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
|
||||
|
@ -1776,6 +1808,11 @@
|
|||
"resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz",
|
||||
"integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0="
|
||||
},
|
||||
"async-foreach": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz",
|
||||
"integrity": "sha1-NhIfhFwFeBct5Bmpfb6x0W7DRUI="
|
||||
},
|
||||
"async-limiter": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
|
||||
|
@ -2451,6 +2488,14 @@
|
|||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz",
|
||||
"integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg=="
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
|
||||
"integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=",
|
||||
"requires": {
|
||||
"inherits": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.5.3",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz",
|
||||
|
@ -2795,6 +2840,22 @@
|
|||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.0.0.tgz",
|
||||
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA=="
|
||||
},
|
||||
"camelcase-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
|
||||
"integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=",
|
||||
"requires": {
|
||||
"camelcase": "^2.0.0",
|
||||
"map-obj": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz",
|
||||
"integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"caniuse-api": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
|
||||
|
@ -3244,6 +3305,11 @@
|
|||
"date-now": "^0.1.4"
|
||||
}
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
|
||||
"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
|
||||
},
|
||||
"constants-browserify": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
|
||||
|
@ -3804,6 +3870,14 @@
|
|||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.0.tgz",
|
||||
"integrity": "sha512-by8hi8BlLbowQq0qtkx54d9aN73R9oUW20HISpka5kmgsR9F7nnxgfsemuR2sdCKZh+CDNf5egW9UZMm4mgJRg=="
|
||||
},
|
||||
"currently-unhandled": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz",
|
||||
"integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=",
|
||||
"requires": {
|
||||
"array-find-index": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"cyclist": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/cyclist/-/cyclist-0.2.2.tgz",
|
||||
|
@ -4002,6 +4076,11 @@
|
|||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
|
||||
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
|
@ -5878,11 +5957,13 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -5895,15 +5976,18 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -6006,7 +6090,8 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -6016,6 +6101,7 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -6028,17 +6114,20 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -6055,6 +6144,7 @@
|
|||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -6127,7 +6217,8 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -6137,6 +6228,7 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -6242,6 +6334,7 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -6305,6 +6398,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.11",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",
|
||||
"integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=",
|
||||
"requires": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"inherits": "~2.0.0",
|
||||
"mkdirp": ">=0.5 0",
|
||||
"rimraf": "2"
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
|
@ -6315,6 +6419,49 @@
|
|||
"resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
|
||||
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc="
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.7.4",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
|
||||
"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
|
||||
"requires": {
|
||||
"aproba": "^1.0.3",
|
||||
"console-control-strings": "^1.0.0",
|
||||
"has-unicode": "^2.0.0",
|
||||
"object-assign": "^4.1.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wide-align": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"gaze": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz",
|
||||
"integrity": "sha512-BRdNm8hbWzFzWHERTrejLqwHDfS4GibPoq5wjTPIoJHoBtKGPg3xAFfxmM+9ztbXelxcf2hwQcaz1PtmFeue8g==",
|
||||
"requires": {
|
||||
"globule": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
|
@ -6325,6 +6472,11 @@
|
|||
"resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz",
|
||||
"integrity": "sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg=="
|
||||
},
|
||||
"get-stdin": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
|
||||
"integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4="
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||
|
@ -6431,6 +6583,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"globule": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.2.1.tgz",
|
||||
"integrity": "sha512-g7QtgWF4uYSL5/dn71WxubOrS7JVGCnFPEnoeChJmBnyR9Mw8nGoEwOgJL/RC2Te0WhbsEUCejfH8SZNJ+adYQ==",
|
||||
"requires": {
|
||||
"glob": "~7.1.1",
|
||||
"lodash": "~4.17.10",
|
||||
"minimatch": "~3.0.2"
|
||||
}
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.1.15",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
|
||||
|
@ -6573,6 +6735,11 @@
|
|||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
|
||||
"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
|
||||
},
|
||||
"has-value": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
|
||||
|
@ -7252,6 +7419,11 @@
|
|||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
|
||||
"integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
|
||||
},
|
||||
"in-publish": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz",
|
||||
"integrity": "sha1-4g/146KvwmkDILbcVSaCqcf631E="
|
||||
},
|
||||
"indefinite-observable": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/indefinite-observable/-/indefinite-observable-1.0.2.tgz",
|
||||
|
@ -7260,6 +7432,14 @@
|
|||
"symbol-observable": "1.2.0"
|
||||
}
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz",
|
||||
"integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=",
|
||||
"requires": {
|
||||
"repeating": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"indexes-of": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
|
||||
|
@ -8327,6 +8507,11 @@
|
|||
"topo": "2.x.x"
|
||||
}
|
||||
},
|
||||
"js-base64": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz",
|
||||
"integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g=="
|
||||
},
|
||||
"js-levenshtein": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.5.tgz",
|
||||
|
@ -8712,11 +8897,21 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
|
||||
"integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0="
|
||||
},
|
||||
"lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc="
|
||||
},
|
||||
"lodash.camelcase": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
|
||||
"integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
|
||||
},
|
||||
"lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8="
|
||||
},
|
||||
"lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
|
||||
|
@ -8727,6 +8922,11 @@
|
|||
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
|
||||
"integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
|
||||
},
|
||||
"lodash.mergewith": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
|
||||
"integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ=="
|
||||
},
|
||||
"lodash.sortby": {
|
||||
"version": "4.7.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
|
||||
|
@ -8772,6 +8972,15 @@
|
|||
"js-tokens": "^3.0.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"loud-rejection": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz",
|
||||
"integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=",
|
||||
"requires": {
|
||||
"currently-unhandled": "^0.4.1",
|
||||
"signal-exit": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"lower-case": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
|
||||
|
@ -8827,6 +9036,11 @@
|
|||
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
|
||||
"integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8="
|
||||
},
|
||||
"map-obj": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
|
||||
"integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0="
|
||||
},
|
||||
"map-visit": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
|
||||
|
@ -8877,6 +9091,23 @@
|
|||
"readable-stream": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"meow": {
|
||||
"version": "3.7.0",
|
||||
"resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz",
|
||||
"integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=",
|
||||
"requires": {
|
||||
"camelcase-keys": "^2.0.0",
|
||||
"decamelize": "^1.1.2",
|
||||
"loud-rejection": "^1.0.0",
|
||||
"map-obj": "^1.0.1",
|
||||
"minimist": "^1.1.3",
|
||||
"normalize-package-data": "^2.3.4",
|
||||
"object-assign": "^4.0.1",
|
||||
"read-pkg-up": "^1.0.1",
|
||||
"redent": "^1.0.0",
|
||||
"trim-newlines": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"merge": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz",
|
||||
|
@ -9107,8 +9338,7 @@
|
|||
"nan": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.12.1.tgz",
|
||||
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw==",
|
||||
"optional": true
|
||||
"integrity": "sha512-JY7V6lRkStKcKTvHO5NVSQRv+RV+FIL5pvDoLiAtSL9pKlC5x9PKQcZDsq7m4FO4d57mkhC6Z+QhAh3Jdk5JFw=="
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
|
@ -9187,6 +9417,32 @@
|
|||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
|
||||
"integrity": "sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ=="
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "3.8.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
|
||||
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
|
||||
"requires": {
|
||||
"fstream": "^1.0.0",
|
||||
"glob": "^7.0.3",
|
||||
"graceful-fs": "^4.1.2",
|
||||
"mkdirp": "^0.5.0",
|
||||
"nopt": "2 || 3",
|
||||
"npmlog": "0 || 1 || 2 || 3 || 4",
|
||||
"osenv": "0",
|
||||
"request": "^2.87.0",
|
||||
"rimraf": "2",
|
||||
"semver": "~5.3.0",
|
||||
"tar": "^2.0.0",
|
||||
"which": "1"
|
||||
},
|
||||
"dependencies": {
|
||||
"semver": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
|
||||
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8="
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-int64": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
|
||||
|
@ -9248,6 +9504,73 @@
|
|||
"semver": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
|
||||
"integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==",
|
||||
"requires": {
|
||||
"async-foreach": "^0.1.3",
|
||||
"chalk": "^1.1.1",
|
||||
"cross-spawn": "^3.0.0",
|
||||
"gaze": "^1.0.0",
|
||||
"get-stdin": "^4.0.1",
|
||||
"glob": "^7.0.3",
|
||||
"in-publish": "^2.0.0",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"lodash.clonedeep": "^4.3.2",
|
||||
"lodash.mergewith": "^4.6.0",
|
||||
"meow": "^3.7.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nan": "^2.10.0",
|
||||
"node-gyp": "^3.8.0",
|
||||
"npmlog": "^4.0.0",
|
||||
"request": "^2.88.0",
|
||||
"sass-graph": "^2.2.4",
|
||||
"stdout-stream": "^1.4.0",
|
||||
"true-case-path": "^1.0.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
|
||||
"integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4="
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"requires": {
|
||||
"ansi-styles": "^2.2.1",
|
||||
"escape-string-regexp": "^1.0.2",
|
||||
"has-ansi": "^2.0.0",
|
||||
"strip-ansi": "^3.0.0",
|
||||
"supports-color": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz",
|
||||
"integrity": "sha1-ElYDfsufDF9549bvE14wdwGEuYI=",
|
||||
"requires": {
|
||||
"lru-cache": "^4.0.1",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc="
|
||||
}
|
||||
}
|
||||
},
|
||||
"nopt": {
|
||||
"version": "3.0.6",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
|
||||
|
@ -9290,6 +9613,17 @@
|
|||
"path-key": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
|
||||
"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
|
||||
"requires": {
|
||||
"are-we-there-yet": "~1.1.2",
|
||||
"console-control-strings": "~1.1.0",
|
||||
"gauge": "~2.7.3",
|
||||
"set-blocking": "~2.0.0"
|
||||
}
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
|
||||
|
@ -9527,6 +9861,15 @@
|
|||
"resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
|
||||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"osenv": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||
"requires": {
|
||||
"os-homedir": "^1.0.0",
|
||||
"os-tmpdir": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
||||
|
@ -14197,6 +14540,15 @@
|
|||
"minimatch": "3.0.4"
|
||||
}
|
||||
},
|
||||
"redent": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz",
|
||||
"integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=",
|
||||
"requires": {
|
||||
"indent-string": "^2.1.0",
|
||||
"strip-indent": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"redux": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/redux/-/redux-4.0.1.tgz",
|
||||
|
@ -14866,6 +15218,93 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"sass-graph": {
|
||||
"version": "2.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz",
|
||||
"integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=",
|
||||
"requires": {
|
||||
"glob": "^7.0.0",
|
||||
"lodash": "^4.0.0",
|
||||
"scss-tokenizer": "^0.2.3",
|
||||
"yargs": "^7.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"camelcase": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
|
||||
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
|
||||
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz",
|
||||
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=",
|
||||
"requires": {
|
||||
"lcid": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
|
||||
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
|
||||
"integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=",
|
||||
"requires": {
|
||||
"camelcase": "^3.0.0",
|
||||
"cliui": "^3.2.0",
|
||||
"decamelize": "^1.1.1",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^1.4.0",
|
||||
"read-pkg-up": "^1.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^1.0.2",
|
||||
"which-module": "^1.0.0",
|
||||
"y18n": "^3.2.1",
|
||||
"yargs-parser": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz",
|
||||
"integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=",
|
||||
"requires": {
|
||||
"camelcase": "^3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"sass-loader": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-7.1.0.tgz",
|
||||
|
@ -14959,6 +15398,25 @@
|
|||
"ajv-keywords": "^3.1.0"
|
||||
}
|
||||
},
|
||||
"scss-tokenizer": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz",
|
||||
"integrity": "sha1-jrBtualyMzOCTT9VMGQRSYR85dE=",
|
||||
"requires": {
|
||||
"js-base64": "^2.1.8",
|
||||
"source-map": "^0.4.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"source-map": {
|
||||
"version": "0.4.4",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz",
|
||||
"integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=",
|
||||
"requires": {
|
||||
"amdefine": ">=0.0.4"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
|
@ -15523,6 +15981,14 @@
|
|||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz",
|
||||
"integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew=="
|
||||
},
|
||||
"stdout-stream": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/stdout-stream/-/stdout-stream-1.4.1.tgz",
|
||||
"integrity": "sha512-j4emi03KXqJWcIeF8eIXkjMFN1Cmb8gUlDYGeBALLPo5qdyTfA9bOtl8m33lRoC+vFMkP3gl0WsDr6+gzxbbTA==",
|
||||
"requires": {
|
||||
"readable-stream": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"stealthy-require": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||
|
@ -15664,6 +16130,14 @@
|
|||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
||||
},
|
||||
"strip-indent": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz",
|
||||
"integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=",
|
||||
"requires": {
|
||||
"get-stdin": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"strip-json-comments": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
|
||||
|
@ -15811,6 +16285,16 @@
|
|||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz",
|
||||
"integrity": "sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA=="
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz",
|
||||
"integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=",
|
||||
"requires": {
|
||||
"block-stream": "*",
|
||||
"fstream": "^1.0.2",
|
||||
"inherits": "2"
|
||||
}
|
||||
},
|
||||
"terser": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/terser/-/terser-3.14.1.tgz",
|
||||
|
@ -16060,11 +16544,24 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"trim-newlines": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz",
|
||||
"integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM="
|
||||
},
|
||||
"trim-right": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz",
|
||||
"integrity": "sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM="
|
||||
},
|
||||
"true-case-path": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz",
|
||||
"integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==",
|
||||
"requires": {
|
||||
"glob": "^7.1.2"
|
||||
}
|
||||
},
|
||||
"tryer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
|
||||
|
@ -17237,6 +17734,14 @@
|
|||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
|
||||
"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
|
||||
"requires": {
|
||||
"string-width": "^1.0.2 || 2"
|
||||
}
|
||||
},
|
||||
"wordwrap": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
"@types/classnames": "^2.2.7",
|
||||
"@types/jss": "^9.5.7",
|
||||
"@types/node": "^10.12.2",
|
||||
"@types/node-sass": "^3.10.32",
|
||||
"@types/qrcode.react": "^0.8.1",
|
||||
"@types/query-string": "^6.2.0",
|
||||
"@types/react": "^16.4.18",
|
||||
|
@ -18,6 +19,7 @@
|
|||
"await-to-js": "^2.1.1",
|
||||
"classnames": "^2.2.6",
|
||||
"jss": "^9.8.7",
|
||||
"node-sass": "^4.11.0",
|
||||
"qrcode.react": "^0.9.2",
|
||||
"query-string": "^6.2.0",
|
||||
"react": "^16.6.0",
|
||||
|
|
129
client-react/src/assets/images/applestore-badge.svg
Normal file
129
client-react/src/assets/images/applestore-badge.svg
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="US_UK_Download_on_the" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
x="0px" y="0px" width="135px" height="40px" viewBox="0 0 135 40" enable-background="new 0 0 135 40" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#A6A6A6" d="M130.197,40H4.729C2.122,40,0,37.872,0,35.267V4.726C0,2.12,2.122,0,4.729,0h125.468
|
||||
C132.803,0,135,2.12,135,4.726v30.541C135,37.872,132.803,40,130.197,40L130.197,40z"/>
|
||||
<path d="M134.032,35.268c0,2.116-1.714,3.83-3.834,3.83H4.729c-2.119,0-3.839-1.714-3.839-3.83V4.725
|
||||
c0-2.115,1.72-3.835,3.839-3.835h125.468c2.121,0,3.834,1.72,3.834,3.835L134.032,35.268L134.032,35.268z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M30.128,19.784c-0.029-3.223,2.639-4.791,2.761-4.864c-1.511-2.203-3.853-2.504-4.676-2.528
|
||||
c-1.967-0.207-3.875,1.177-4.877,1.177c-1.022,0-2.565-1.157-4.228-1.123c-2.14,0.033-4.142,1.272-5.24,3.196
|
||||
c-2.266,3.923-0.576,9.688,1.595,12.859c1.086,1.553,2.355,3.287,4.016,3.226c1.625-0.067,2.232-1.036,4.193-1.036
|
||||
c1.943,0,2.513,1.036,4.207,0.997c1.744-0.028,2.842-1.56,3.89-3.127c1.255-1.78,1.759-3.533,1.779-3.623
|
||||
C33.507,24.924,30.161,23.647,30.128,19.784z"/>
|
||||
<path fill="#FFFFFF" d="M26.928,10.306c0.874-1.093,1.472-2.58,1.306-4.089c-1.265,0.056-2.847,0.875-3.758,1.944
|
||||
c-0.806,0.942-1.526,2.486-1.34,3.938C24.557,12.205,26.016,11.382,26.928,10.306z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M53.645,31.504h-2.271l-1.244-3.909h-4.324l-1.185,3.909h-2.211l4.284-13.308h2.646L53.645,31.504z
|
||||
M49.755,25.955L48.63,22.48c-0.119-0.355-0.342-1.191-0.671-2.507h-0.04c-0.131,0.566-0.342,1.402-0.632,2.507l-1.105,3.475
|
||||
H49.755z"/>
|
||||
<path fill="#FFFFFF" d="M64.662,26.588c0,1.632-0.441,2.922-1.323,3.869c-0.79,0.843-1.771,1.264-2.942,1.264
|
||||
c-1.264,0-2.172-0.454-2.725-1.362h-0.04v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.711-1.146,1.79-1.718,3.238-1.718c1.132,0,2.077,0.447,2.833,1.342C64.284,23.949,64.662,25.127,64.662,26.588z M62.49,26.666
|
||||
c0-0.934-0.21-1.704-0.632-2.31c-0.461-0.632-1.08-0.948-1.856-0.948c-0.526,0-1.004,0.176-1.431,0.523
|
||||
c-0.428,0.35-0.708,0.807-0.839,1.373c-0.066,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.642,1.768
|
||||
s0.984,0.721,1.668,0.721c0.803,0,1.428-0.31,1.875-0.928C62.266,28.496,62.49,27.68,62.49,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M75.699,26.588c0,1.632-0.441,2.922-1.324,3.869c-0.789,0.843-1.77,1.264-2.941,1.264
|
||||
c-1.264,0-2.172-0.454-2.724-1.362H68.67v5.055h-2.132V25.067c0-1.026-0.027-2.079-0.079-3.159h1.875l0.119,1.521h0.04
|
||||
c0.71-1.146,1.789-1.718,3.238-1.718c1.131,0,2.076,0.447,2.834,1.342C75.32,23.949,75.699,25.127,75.699,26.588z M73.527,26.666
|
||||
c0-0.934-0.211-1.704-0.633-2.31c-0.461-0.632-1.078-0.948-1.855-0.948c-0.527,0-1.004,0.176-1.432,0.523
|
||||
c-0.428,0.35-0.707,0.807-0.838,1.373c-0.065,0.264-0.099,0.48-0.099,0.65v1.6c0,0.698,0.214,1.287,0.64,1.768
|
||||
c0.428,0.48,0.984,0.721,1.67,0.721c0.803,0,1.428-0.31,1.875-0.928C73.303,28.496,73.527,27.68,73.527,26.666z"/>
|
||||
<path fill="#FFFFFF" d="M88.039,27.772c0,1.132-0.393,2.053-1.182,2.764c-0.867,0.777-2.074,1.165-3.625,1.165
|
||||
c-1.432,0-2.58-0.276-3.449-0.829l0.494-1.777c0.936,0.566,1.963,0.85,3.082,0.85c0.803,0,1.428-0.182,1.877-0.544
|
||||
c0.447-0.362,0.67-0.848,0.67-1.454c0-0.54-0.184-0.995-0.553-1.364c-0.367-0.369-0.98-0.712-1.836-1.029
|
||||
c-2.33-0.869-3.494-2.142-3.494-3.816c0-1.094,0.408-1.991,1.225-2.689c0.814-0.699,1.9-1.048,3.258-1.048
|
||||
c1.211,0,2.217,0.211,3.02,0.632l-0.533,1.738c-0.75-0.408-1.598-0.612-2.547-0.612c-0.75,0-1.336,0.185-1.756,0.553
|
||||
c-0.355,0.329-0.533,0.73-0.533,1.205c0,0.526,0.203,0.961,0.611,1.303c0.355,0.316,1,0.658,1.936,1.027
|
||||
c1.145,0.461,1.986,1,2.527,1.618C87.77,26.081,88.039,26.852,88.039,27.772z"/>
|
||||
<path fill="#FFFFFF" d="M95.088,23.508h-2.35v4.659c0,1.185,0.414,1.777,1.244,1.777c0.381,0,0.697-0.033,0.947-0.099l0.059,1.619
|
||||
c-0.42,0.157-0.973,0.236-1.658,0.236c-0.842,0-1.5-0.257-1.975-0.77c-0.473-0.514-0.711-1.376-0.711-2.587v-4.837h-1.4v-1.6h1.4
|
||||
v-1.757l2.094-0.632v2.389h2.35V23.508z"/>
|
||||
<path fill="#FFFFFF" d="M105.691,26.627c0,1.475-0.422,2.686-1.264,3.633c-0.883,0.975-2.055,1.461-3.516,1.461
|
||||
c-1.408,0-2.529-0.467-3.365-1.401s-1.254-2.113-1.254-3.534c0-1.487,0.43-2.705,1.293-3.652c0.861-0.948,2.023-1.422,3.484-1.422
|
||||
c1.408,0,2.541,0.467,3.396,1.402C105.283,24.021,105.691,25.192,105.691,26.627z M103.479,26.696
|
||||
c0-0.885-0.189-1.644-0.572-2.277c-0.447-0.766-1.086-1.148-1.914-1.148c-0.857,0-1.508,0.383-1.955,1.148
|
||||
c-0.383,0.634-0.572,1.405-0.572,2.317c0,0.885,0.189,1.644,0.572,2.276c0.461,0.766,1.105,1.148,1.936,1.148
|
||||
c0.814,0,1.453-0.39,1.914-1.168C103.281,28.347,103.479,27.58,103.479,26.696z"/>
|
||||
<path fill="#FFFFFF" d="M112.621,23.783c-0.211-0.039-0.436-0.059-0.672-0.059c-0.75,0-1.33,0.283-1.738,0.85
|
||||
c-0.355,0.5-0.533,1.132-0.533,1.895v5.035h-2.131l0.02-6.574c0-1.106-0.027-2.113-0.08-3.021h1.857l0.078,1.836h0.059
|
||||
c0.225-0.631,0.58-1.139,1.066-1.52c0.475-0.343,0.988-0.514,1.541-0.514c0.197,0,0.375,0.014,0.533,0.039V23.783z"/>
|
||||
<path fill="#FFFFFF" d="M122.156,26.252c0,0.382-0.025,0.704-0.078,0.967h-6.396c0.025,0.948,0.334,1.673,0.928,2.173
|
||||
c0.539,0.447,1.236,0.671,2.092,0.671c0.947,0,1.811-0.151,2.588-0.454l0.334,1.48c-0.908,0.396-1.98,0.593-3.217,0.593
|
||||
c-1.488,0-2.656-0.438-3.506-1.313c-0.848-0.875-1.273-2.05-1.273-3.524c0-1.447,0.395-2.652,1.186-3.613
|
||||
c0.828-1.026,1.947-1.539,3.355-1.539c1.383,0,2.43,0.513,3.141,1.539C121.873,24.047,122.156,25.055,122.156,26.252z
|
||||
M120.123,25.699c0.014-0.632-0.125-1.178-0.414-1.639c-0.369-0.593-0.936-0.889-1.699-0.889c-0.697,0-1.264,0.289-1.697,0.869
|
||||
c-0.355,0.461-0.566,1.014-0.631,1.658H120.123z"/>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M49.05,10.009c0,1.177-0.353,2.063-1.058,2.658c-0.653,0.549-1.581,0.824-2.783,0.824
|
||||
c-0.596,0-1.106-0.026-1.533-0.078V6.982c0.557-0.09,1.157-0.136,1.805-0.136c1.145,0,2.008,0.249,2.59,0.747
|
||||
C48.723,8.156,49.05,8.961,49.05,10.009z M47.945,10.038c0-0.763-0.202-1.348-0.606-1.756c-0.404-0.407-0.994-0.611-1.771-0.611
|
||||
c-0.33,0-0.611,0.022-0.844,0.068v4.889c0.129,0.02,0.365,0.029,0.708,0.029c0.802,0,1.421-0.223,1.857-0.669
|
||||
S47.945,10.892,47.945,10.038z"/>
|
||||
<path fill="#FFFFFF" d="M54.909,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.009,0.718-1.727,0.718
|
||||
c-0.692,0-1.243-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.712-0.698
|
||||
c0.692,0,1.248,0.229,1.669,0.688C54.708,9.757,54.909,10.333,54.909,11.037z M53.822,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.22-0.376-0.533-0.564-0.94-0.564c-0.421,0-0.741,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.714-0.191,0.94-0.574
|
||||
C53.725,11.882,53.822,11.506,53.822,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M62.765,8.719l-1.475,4.714h-0.96l-0.611-2.047c-0.155-0.511-0.281-1.019-0.379-1.523h-0.019
|
||||
c-0.091,0.518-0.217,1.025-0.379,1.523l-0.649,2.047h-0.971l-1.387-4.714h1.077l0.533,2.241c0.129,0.53,0.235,1.035,0.32,1.513
|
||||
h0.019c0.078-0.394,0.207-0.896,0.389-1.503l0.669-2.25h0.854l0.641,2.202c0.155,0.537,0.281,1.054,0.378,1.552h0.029
|
||||
c0.071-0.485,0.178-1.002,0.32-1.552l0.572-2.202H62.765z"/>
|
||||
<path fill="#FFFFFF" d="M68.198,13.433H67.15v-2.7c0-0.832-0.316-1.248-0.95-1.248c-0.311,0-0.562,0.114-0.757,0.343
|
||||
c-0.193,0.229-0.291,0.499-0.291,0.808v2.796h-1.048v-3.366c0-0.414-0.013-0.863-0.038-1.349h0.921l0.049,0.737h0.029
|
||||
c0.122-0.229,0.304-0.418,0.543-0.569c0.284-0.176,0.602-0.265,0.95-0.265c0.44,0,0.806,0.142,1.097,0.427
|
||||
c0.362,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M71.088,13.433h-1.047V6.556h1.047V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M77.258,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.01,0.718-1.727,0.718
|
||||
c-0.693,0-1.244-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.711-0.698
|
||||
c0.693,0,1.248,0.229,1.67,0.688C77.057,9.757,77.258,10.333,77.258,11.037z M76.17,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.219-0.376-0.533-0.564-0.939-0.564c-0.422,0-0.742,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.713-0.191,0.939-0.574
|
||||
C76.074,11.882,76.17,11.506,76.17,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M82.33,13.433h-0.941l-0.078-0.543h-0.029c-0.322,0.433-0.781,0.65-1.377,0.65
|
||||
c-0.445,0-0.805-0.143-1.076-0.427c-0.246-0.258-0.369-0.579-0.369-0.96c0-0.576,0.24-1.015,0.723-1.319
|
||||
c0.482-0.304,1.16-0.453,2.033-0.446V10.3c0-0.621-0.326-0.931-0.979-0.931c-0.465,0-0.875,0.117-1.229,0.349l-0.213-0.688
|
||||
c0.438-0.271,0.979-0.407,1.617-0.407c1.232,0,1.85,0.65,1.85,1.95v1.736C82.262,12.78,82.285,13.155,82.33,13.433z
|
||||
M81.242,11.813v-0.727c-1.156-0.02-1.734,0.297-1.734,0.95c0,0.246,0.066,0.43,0.201,0.553c0.135,0.123,0.307,0.184,0.512,0.184
|
||||
c0.23,0,0.445-0.073,0.641-0.218c0.197-0.146,0.318-0.331,0.363-0.558C81.236,11.946,81.242,11.884,81.242,11.813z"/>
|
||||
<path fill="#FFFFFF" d="M88.285,13.433h-0.93l-0.049-0.757h-0.029c-0.297,0.576-0.803,0.864-1.514,0.864
|
||||
c-0.568,0-1.041-0.223-1.416-0.669s-0.562-1.025-0.562-1.736c0-0.763,0.203-1.381,0.611-1.853c0.395-0.44,0.879-0.66,1.455-0.66
|
||||
c0.633,0,1.076,0.213,1.328,0.64h0.02V6.556h1.049v5.607C88.248,12.622,88.26,13.045,88.285,13.433z M87.199,11.445v-0.786
|
||||
c0-0.136-0.01-0.246-0.029-0.33c-0.059-0.252-0.186-0.464-0.379-0.635c-0.195-0.171-0.43-0.257-0.701-0.257
|
||||
c-0.391,0-0.697,0.155-0.922,0.466c-0.223,0.311-0.336,0.708-0.336,1.193c0,0.466,0.107,0.844,0.322,1.135
|
||||
c0.227,0.31,0.533,0.465,0.916,0.465c0.344,0,0.619-0.129,0.828-0.388C87.1,12.069,87.199,11.781,87.199,11.445z"/>
|
||||
<path fill="#FFFFFF" d="M97.248,11.037c0,0.725-0.207,1.319-0.621,1.785c-0.434,0.479-1.008,0.718-1.727,0.718
|
||||
c-0.691,0-1.242-0.229-1.654-0.689c-0.41-0.459-0.615-1.038-0.615-1.736c0-0.73,0.211-1.329,0.635-1.794s0.994-0.698,1.713-0.698
|
||||
c0.691,0,1.248,0.229,1.668,0.688C97.047,9.757,97.248,10.333,97.248,11.037z M96.162,11.071c0-0.435-0.094-0.808-0.281-1.119
|
||||
c-0.221-0.376-0.533-0.564-0.941-0.564c-0.42,0-0.74,0.188-0.961,0.564c-0.188,0.311-0.281,0.69-0.281,1.138
|
||||
c0,0.435,0.094,0.808,0.281,1.119c0.227,0.376,0.543,0.564,0.951,0.564c0.4,0,0.715-0.191,0.941-0.574
|
||||
C96.064,11.882,96.162,11.506,96.162,11.071z"/>
|
||||
<path fill="#FFFFFF" d="M102.883,13.433h-1.047v-2.7c0-0.832-0.316-1.248-0.951-1.248c-0.311,0-0.562,0.114-0.756,0.343
|
||||
s-0.291,0.499-0.291,0.808v2.796h-1.049v-3.366c0-0.414-0.012-0.863-0.037-1.349h0.92l0.049,0.737h0.029
|
||||
c0.123-0.229,0.305-0.418,0.543-0.569c0.285-0.176,0.602-0.265,0.951-0.265c0.439,0,0.805,0.142,1.096,0.427
|
||||
c0.363,0.349,0.543,0.87,0.543,1.562V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M109.936,9.504h-1.154v2.29c0,0.582,0.205,0.873,0.611,0.873c0.188,0,0.344-0.016,0.467-0.049
|
||||
l0.027,0.795c-0.207,0.078-0.479,0.117-0.814,0.117c-0.414,0-0.736-0.126-0.969-0.378c-0.234-0.252-0.35-0.676-0.35-1.271V9.504
|
||||
h-0.689V8.719h0.689V7.855l1.027-0.31v1.173h1.154V9.504z"/>
|
||||
<path fill="#FFFFFF" d="M115.484,13.433h-1.049v-2.68c0-0.845-0.316-1.268-0.949-1.268c-0.486,0-0.818,0.245-1,0.735
|
||||
c-0.031,0.103-0.049,0.229-0.049,0.377v2.835h-1.047V6.556h1.047v2.841h0.02c0.33-0.517,0.803-0.775,1.416-0.775
|
||||
c0.434,0,0.793,0.142,1.078,0.427c0.355,0.355,0.533,0.883,0.533,1.581V13.433z"/>
|
||||
<path fill="#FFFFFF" d="M121.207,10.853c0,0.188-0.014,0.346-0.039,0.475h-3.143c0.014,0.466,0.164,0.821,0.455,1.067
|
||||
c0.266,0.22,0.609,0.33,1.029,0.33c0.465,0,0.889-0.074,1.271-0.223l0.164,0.728c-0.447,0.194-0.973,0.291-1.582,0.291
|
||||
c-0.73,0-1.305-0.215-1.721-0.645c-0.418-0.43-0.625-1.007-0.625-1.731c0-0.711,0.193-1.303,0.582-1.775
|
||||
c0.406-0.504,0.955-0.756,1.648-0.756c0.678,0,1.193,0.252,1.541,0.756C121.068,9.77,121.207,10.265,121.207,10.853z
|
||||
M120.207,10.582c0.008-0.311-0.061-0.579-0.203-0.805c-0.182-0.291-0.459-0.437-0.834-0.437c-0.342,0-0.621,0.142-0.834,0.427
|
||||
c-0.174,0.227-0.277,0.498-0.311,0.815H120.207z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 12 KiB |
429
client-react/src/assets/images/googleplay-badge.svg
Normal file
429
client-react/src/assets/images/googleplay-badge.svg
Normal file
|
@ -0,0 +1,429 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
xml:space="preserve"
|
||||
width="135.71649"
|
||||
height="40.018951"
|
||||
viewBox="0 0 135.71649 40.018951"
|
||||
sodipodi:docname="google-play-badge.svg"><metadata
|
||||
id="metadata8"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs6"><linearGradient
|
||||
x1="31.7997"
|
||||
y1="183.2903"
|
||||
x2="15.0173"
|
||||
y2="166.5079"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8,0,0,-0.8,0,161.6)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient50"><stop
|
||||
style="stop-opacity:1;stop-color:#00a0ff"
|
||||
offset="0"
|
||||
id="stop52" /><stop
|
||||
style="stop-opacity:1;stop-color:#00a1ff"
|
||||
offset="0.0066"
|
||||
id="stop54" /><stop
|
||||
style="stop-opacity:1;stop-color:#00beff"
|
||||
offset="0.2601"
|
||||
id="stop56" /><stop
|
||||
style="stop-opacity:1;stop-color:#00d2ff"
|
||||
offset="0.5122"
|
||||
id="stop58" /><stop
|
||||
style="stop-opacity:1;stop-color:#00dfff"
|
||||
offset="0.7604"
|
||||
id="stop60" /><stop
|
||||
style="stop-opacity:1;stop-color:#00e3ff"
|
||||
offset="1"
|
||||
id="stop62" /></linearGradient><linearGradient
|
||||
x1="43.8344"
|
||||
y1="171.9986"
|
||||
x2="19.637501"
|
||||
y2="171.9986"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8,0,0,-0.8,0,161.6)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient68"><stop
|
||||
style="stop-opacity:1;stop-color:#ffe000"
|
||||
offset="0"
|
||||
id="stop70" /><stop
|
||||
style="stop-opacity:1;stop-color:#ffbd00"
|
||||
offset="0.4087"
|
||||
id="stop72" /><stop
|
||||
style="stop-opacity:1;stop-color:#ffa500"
|
||||
offset="0.7754"
|
||||
id="stop74" /><stop
|
||||
style="stop-opacity:1;stop-color:#ff9c00"
|
||||
offset="1"
|
||||
id="stop76" /></linearGradient><linearGradient
|
||||
x1="34.827"
|
||||
y1="169.7039"
|
||||
x2="12.0687"
|
||||
y2="146.9456"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8,0,0,-0.8,0,161.6)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient82"><stop
|
||||
style="stop-opacity:1;stop-color:#ff3a44"
|
||||
offset="0"
|
||||
id="stop84" /><stop
|
||||
style="stop-opacity:1;stop-color:#c31162"
|
||||
offset="1"
|
||||
id="stop86" /></linearGradient><linearGradient
|
||||
x1="17.2973"
|
||||
y1="191.82381"
|
||||
x2="27.4599"
|
||||
y2="181.6613"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(0.8,0,0,-0.8,0,161.6)"
|
||||
spreadMethod="pad"
|
||||
id="linearGradient92"><stop
|
||||
style="stop-opacity:1;stop-color:#32a071"
|
||||
offset="0"
|
||||
id="stop94" /><stop
|
||||
style="stop-opacity:1;stop-color:#2da771"
|
||||
offset="0.0685"
|
||||
id="stop96" /><stop
|
||||
style="stop-opacity:1;stop-color:#15cf74"
|
||||
offset="0.4762"
|
||||
id="stop98" /><stop
|
||||
style="stop-opacity:1;stop-color:#06e775"
|
||||
offset="0.8009"
|
||||
id="stop100" /><stop
|
||||
style="stop-opacity:1;stop-color:#00f076"
|
||||
offset="1"
|
||||
id="stop102" /></linearGradient><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath110"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path112"
|
||||
inkscape:connector-curvature="0" /></clipPath><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1"
|
||||
id="mask114"><g
|
||||
id="g116"><g
|
||||
clip-path="url(#clipPath110)"
|
||||
id="g118"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:0.2;fill-rule:nonzero;stroke:none"
|
||||
id="path120"
|
||||
inkscape:connector-curvature="0" /></g></g></mask><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath126"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path128"
|
||||
inkscape:connector-curvature="0" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath130"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path132"
|
||||
inkscape:connector-curvature="0" /></clipPath><pattern
|
||||
patternTransform="matrix(1,0,0,-1,0,48)"
|
||||
patternUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="124"
|
||||
height="48"
|
||||
id="pattern134"><g
|
||||
id="g136" /><g
|
||||
id="g138"><g
|
||||
clip-path="url(#clipPath130)"
|
||||
id="g140"><g
|
||||
id="g142"><path
|
||||
d="M 29.625,20.695 18.012,14.098 C 17.363,13.727 16.781,13.754 16.406,14.09 l -0.058,-0.063 0.058,-0.058 c 0.375,-0.336 0.957,-0.36 1.606,0.011 l 11.687,6.641 -0.074,0.074 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path144" /></g></g></g></pattern><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath158"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path160"
|
||||
inkscape:connector-curvature="0" /></clipPath><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1"
|
||||
id="mask162"><g
|
||||
id="g164"><g
|
||||
clip-path="url(#clipPath158)"
|
||||
id="g166"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:0.12000002;fill-rule:nonzero;stroke:none"
|
||||
id="path168"
|
||||
inkscape:connector-curvature="0" /></g></g></mask><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath174"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path176"
|
||||
inkscape:connector-curvature="0" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath178"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path180"
|
||||
inkscape:connector-curvature="0" /></clipPath><pattern
|
||||
patternTransform="matrix(1,0,0,-1,0,48)"
|
||||
patternUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="124"
|
||||
height="48"
|
||||
id="pattern182"><g
|
||||
id="g184" /><g
|
||||
id="g186"><g
|
||||
clip-path="url(#clipPath178)"
|
||||
id="g188"><g
|
||||
id="g190"><path
|
||||
d="m 16.348,14.145 c -0.235,0.246 -0.371,0.628 -0.371,1.125 l 0,-0.118 c 0,-0.496 0.136,-0.879 0.371,-1.125 l 0.058,0.063 -0.058,0.055 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path192" /></g></g></g></pattern><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath206"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path208"
|
||||
inkscape:connector-curvature="0" /></clipPath><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1"
|
||||
id="mask210"><g
|
||||
id="g212"><g
|
||||
clip-path="url(#clipPath206)"
|
||||
id="g214"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:0.12000002;fill-rule:nonzero;stroke:none"
|
||||
id="path216"
|
||||
inkscape:connector-curvature="0" /></g></g></mask><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath222"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path224"
|
||||
inkscape:connector-curvature="0" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath226"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path228"
|
||||
inkscape:connector-curvature="0" /></clipPath><pattern
|
||||
patternTransform="matrix(1,0,0,-1,0,48)"
|
||||
patternUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="124"
|
||||
height="48"
|
||||
id="pattern230"><g
|
||||
id="g232" /><g
|
||||
id="g234"><g
|
||||
clip-path="url(#clipPath226)"
|
||||
id="g236"><g
|
||||
id="g238"><path
|
||||
d="m 33.613,22.961 -3.988,-2.266 0.074,-0.074 3.914,2.223 c 0.559,0.316 0.836,0.734 0.836,1.156 -0.047,-0.379 -0.332,-0.75 -0.836,-1.039 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path240" /></g></g></g></pattern><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath254"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path256"
|
||||
inkscape:connector-curvature="0" /></clipPath><mask
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="1"
|
||||
height="1"
|
||||
id="mask258"><g
|
||||
id="g260"><g
|
||||
clip-path="url(#clipPath254)"
|
||||
id="g262"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:#000000;fill-opacity:0.25;fill-rule:nonzero;stroke:none"
|
||||
id="path264"
|
||||
inkscape:connector-curvature="0" /></g></g></mask><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath270"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path272"
|
||||
inkscape:connector-curvature="0" /></clipPath><clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath274"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
id="path276"
|
||||
inkscape:connector-curvature="0" /></clipPath><pattern
|
||||
patternTransform="matrix(1,0,0,-1,0,48)"
|
||||
patternUnits="userSpaceOnUse"
|
||||
x="0"
|
||||
y="0"
|
||||
width="124"
|
||||
height="48"
|
||||
id="pattern278"><g
|
||||
id="g280" /><g
|
||||
id="g282"><g
|
||||
clip-path="url(#clipPath274)"
|
||||
id="g284"><g
|
||||
id="g286"><path
|
||||
d="m 18.012,33.902 15.601,-8.863 c 0.508,-0.289 0.789,-0.66 0.836,-1.039 0,0.418 -0.277,0.836 -0.836,1.156 L 18.012,34.02 c -1.117,0.632 -2.035,0.105 -2.035,-1.176 l 0,-0.114 c 0,1.278 0.918,1.805 2.035,1.172 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path288" /></g></g></g></pattern></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1366"
|
||||
inkscape:window-height="705"
|
||||
id="namedview4"
|
||||
showgrid="false"
|
||||
inkscape:zoom="7.6276974"
|
||||
inkscape:cx="93.965168"
|
||||
inkscape:cy="29.61582"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g10" /><g
|
||||
id="g10"
|
||||
inkscape:groupmode="layer"
|
||||
inkscape:label="google-play-badge"
|
||||
transform="matrix(1.25,0,0,-1.25,-9.4247625,49.85025)"><g
|
||||
id="g12"
|
||||
transform="matrix(1.0023923,0,0,0.99072975,-0.29664807,0)"><path
|
||||
d="M 112,8 12,8 C 9.801,8 8,9.801 8,12 l 0,24 c 0,2.199 1.801,4 4,4 l 100,0 c 2.199,0 4,-1.801 4,-4 l 0,-24 c 0,-2.199 -1.801,-4 -4,-4 z"
|
||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path14"
|
||||
inkscape:connector-curvature="0" /><path
|
||||
d="m 112,39.359 c 1.852,0 3.359,-1.507 3.359,-3.359 l 0,-24 c 0,-1.852 -1.507,-3.359 -3.359,-3.359 l -100,0 c -1.852,0 -3.359,1.507 -3.359,3.359 l 0,24 c 0,1.852 1.507,3.359 3.359,3.359 l 100,0 M 112,40 12,40 C 9.801,40 8,38.199 8,36 L 8,12 C 8,9.801 9.801,8 12,8 l 100,0 c 2.199,0 4,1.801 4,4 l 0,24 c 0,2.199 -1.801,4 -4,4 z"
|
||||
style="fill:#a6a6a6;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0" /><g
|
||||
id="g18"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 45.934,16.195 c 0,0.668 -0.2,1.203 -0.594,1.602 -0.453,0.473 -1.043,0.711 -1.766,0.711 -0.691,0 -1.281,-0.242 -1.765,-0.719 -0.485,-0.484 -0.727,-1.078 -0.727,-1.789 0,-0.711 0.242,-1.305 0.727,-1.785 0.484,-0.481 1.074,-0.723 1.765,-0.723 0.344,0 0.672,0.071 0.985,0.203 0.312,0.133 0.566,0.313 0.75,0.535 l -0.418,0.422 c -0.321,-0.379 -0.758,-0.566 -1.317,-0.566 -0.504,0 -0.941,0.176 -1.312,0.531 -0.367,0.356 -0.551,0.817 -0.551,1.383 0,0.566 0.184,1.031 0.551,1.387 0.371,0.351 0.808,0.531 1.312,0.531 0.535,0 0.985,-0.18 1.34,-0.535 0.234,-0.235 0.367,-0.559 0.402,-0.973 l -1.742,0 0,-0.578 2.324,0 c 0.028,0.125 0.036,0.246 0.036,0.363 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path20"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g22"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 49.621,14.191 -2.183,0 0,1.52 1.968,0 0,0.578 -1.968,0 0,1.52 2.183,0 0,0.589 -2.801,0 0,-4.796 2.801,0 0,0.589 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path24"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g26"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 52.223,18.398 -0.618,0 0,-4.207 -1.339,0 0,-0.589 3.297,0 0,0.589 -1.34,0 0,4.207 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path28"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g30"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 55.949,18.398 0,-4.796 0.617,0 0,4.796 -0.617,0 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path32"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g34"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 59.301,18.398 -0.613,0 0,-4.207 -1.344,0 0,-0.589 3.301,0 0,0.589 -1.344,0 0,4.207 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path36"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g38"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 66.887,17.781 c -0.473,0.485 -1.059,0.727 -1.758,0.727 -0.703,0 -1.289,-0.242 -1.762,-0.727 C 62.895,17.297 62.66,16.703 62.66,16 c 0,-0.703 0.235,-1.297 0.707,-1.781 0.473,-0.485 1.059,-0.727 1.762,-0.727 0.695,0 1.281,0.242 1.754,0.731 0.476,0.488 0.711,1.078 0.711,1.777 0,0.703 -0.235,1.297 -0.707,1.781 z m -3.063,-0.402 c 0.356,0.359 0.789,0.539 1.305,0.539 0.512,0 0.949,-0.18 1.301,-0.539 0.355,-0.359 0.535,-0.82 0.535,-1.379 0,-0.559 -0.18,-1.02 -0.535,-1.379 -0.352,-0.359 -0.789,-0.539 -1.301,-0.539 -0.516,0 -0.949,0.18 -1.305,0.539 -0.355,0.359 -0.535,0.82 -0.535,1.379 0,0.559 0.18,1.02 0.535,1.379 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path40"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g42"
|
||||
transform="matrix(1,0,0,-1,0,48)"><path
|
||||
d="m 68.461,18.398 0,-4.796 0.75,0 2.332,3.73 0.027,0 -0.027,-0.922 0,-2.808 0.617,0 0,4.796 -0.644,0 -2.442,-3.914 -0.027,0 0.027,0.926 0,2.988 -0.613,0 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:0.16;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path44"
|
||||
inkscape:connector-curvature="0" /></g><path
|
||||
d="m 62.508,22.598 c -1.879,0 -3.414,-1.43 -3.414,-3.403 0,-1.957 1.535,-3.402 3.414,-3.402 1.883,0 3.418,1.445 3.418,3.402 0,1.973 -1.535,3.403 -3.418,3.403 z m 0,-5.465 c -1.031,0 -1.918,0.851 -1.918,2.062 0,1.227 0.887,2.063 1.918,2.063 1.031,0 1.922,-0.836 1.922,-2.063 0,-1.211 -0.891,-2.062 -1.922,-2.062 z m -7.449,5.465 c -1.883,0 -3.414,-1.43 -3.414,-3.403 0,-1.957 1.531,-3.402 3.414,-3.402 1.882,0 3.414,1.445 3.414,3.402 0,1.973 -1.532,3.403 -3.414,3.403 z m 0,-5.465 c -1.032,0 -1.922,0.851 -1.922,2.062 0,1.227 0.89,2.063 1.922,2.063 1.031,0 1.918,-0.836 1.918,-2.063 0,-1.211 -0.887,-2.062 -1.918,-2.062 z m -8.864,4.422 0,-1.446 3.453,0 c -0.101,-0.808 -0.371,-1.402 -0.785,-1.816 -0.504,-0.5 -1.289,-1.055 -2.668,-1.055 -2.125,0 -3.789,1.715 -3.789,3.84 0,2.125 1.664,3.84 3.789,3.84 1.149,0 1.985,-0.449 2.602,-1.031 l 1.019,1.019 c -0.863,0.824 -2.011,1.457 -3.621,1.457 -2.914,0 -5.363,-2.371 -5.363,-5.285 0,-2.914 2.449,-5.285 5.363,-5.285 1.575,0 2.758,0.516 3.688,1.484 0.953,0.953 1.25,2.293 1.25,3.375 0,0.336 -0.028,0.645 -0.078,0.903 l -4.86,0 z m 36.246,-1.121 c -0.281,0.761 -1.148,2.164 -2.914,2.164 -1.75,0 -3.207,-1.379 -3.207,-3.403 0,-1.906 1.442,-3.402 3.375,-3.402 1.563,0 2.465,0.953 2.836,1.508 l -1.16,0.773 c -0.387,-0.566 -0.914,-0.941 -1.676,-0.941 -0.757,0 -1.3,0.347 -1.648,1.031 l 4.551,1.883 -0.157,0.387 z m -4.64,-1.133 c -0.039,1.312 1.019,1.984 1.777,1.984 0.594,0 1.098,-0.297 1.266,-0.722 L 77.801,19.301 Z M 74.102,16 l 1.496,0 0,10 -1.496,0 0,-10 z m -2.45,5.84 -0.05,0 c -0.336,0.398 -0.977,0.758 -1.789,0.758 -1.704,0 -3.262,-1.496 -3.262,-3.414 0,-1.907 1.558,-3.391 3.262,-3.391 0.812,0 1.453,0.363 1.789,0.773 l 0.05,0 0,-0.488 c 0,-1.301 -0.695,-2 -1.816,-2 -0.914,0 -1.481,0.66 -1.715,1.215 L 66.82,14.75 c 0.375,-0.902 1.368,-2.012 3.016,-2.012 1.754,0 3.234,1.032 3.234,3.543 l 0,6.11 -1.418,0 0,-0.551 z m -1.711,-4.707 c -1.031,0 -1.894,0.863 -1.894,2.051 0,1.199 0.863,2.074 1.894,2.074 1.016,0 1.817,-0.875 1.817,-2.074 0,-1.188 -0.801,-2.051 -1.817,-2.051 z M 89.445,26 l -3.578,0 0,-10 1.492,0 0,3.789 2.086,0 c 1.657,0 3.282,1.199 3.282,3.106 0,1.906 -1.629,3.105 -3.282,3.105 z m 0.039,-4.82 -2.125,0 0,3.429 2.125,0 c 1.114,0 1.75,-0.925 1.75,-1.714 0,-0.774 -0.636,-1.715 -1.75,-1.715 z m 9.223,1.437 c -1.078,0 -2.199,-0.476 -2.66,-1.531 l 1.324,-0.555 c 0.285,0.555 0.809,0.735 1.363,0.735 0.774,0 1.559,-0.465 1.571,-1.286 l 0,-0.105 c -0.27,0.156 -0.848,0.387 -1.559,0.387 -1.426,0 -2.879,-0.785 -2.879,-2.25 0,-1.34 1.168,-2.203 2.481,-2.203 1.004,0 1.558,0.453 1.906,0.98 l 0.051,0 0,-0.773 1.441,0 0,3.836 c 0,1.773 -1.324,2.765 -3.039,2.765 z m -0.18,-5.48 c -0.488,0 -1.168,0.242 -1.168,0.847 0,0.774 0.848,1.071 1.582,1.071 0.657,0 0.965,-0.145 1.364,-0.336 -0.117,-0.926 -0.914,-1.582 -1.778,-1.582 z m 8.469,5.261 -1.715,-4.335 -0.051,0 -1.773,4.335 -1.609,0 2.664,-6.058 -1.52,-3.371 1.559,0 4.105,9.429 -1.66,0 z M 93.547,16 l 1.496,0 0,10 -1.496,0 0,-10 z"
|
||||
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path46"
|
||||
inkscape:connector-curvature="0" /><g
|
||||
id="g48"><path
|
||||
d="M 16.348,33.969 C 16.113,33.723 15.977,33.34 15.977,32.844 l 0,-17.692 c 0,-0.496 0.136,-0.879 0.371,-1.125 l 0.058,-0.054 9.914,9.91 0,0.234 -9.914,9.91 -0.058,-0.058 z"
|
||||
style="fill:url(#linearGradient50);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path64"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g66"><path
|
||||
d="m 29.621,20.578 -3.301,3.305 0,0.234 3.305,3.305 0.074,-0.043 3.914,-2.227 c 1.117,-0.632 1.117,-1.672 0,-2.308 l -3.914,-2.223 -0.078,-0.043 z"
|
||||
style="fill:url(#linearGradient68);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path78"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g80"><path
|
||||
d="M 29.699,20.621 26.32,24 16.348,14.027 c 0.371,-0.39 0.976,-0.437 1.664,-0.047 l 11.687,6.641"
|
||||
style="fill:url(#linearGradient82);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path88"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g90"><path
|
||||
d="M 29.699,27.379 18.012,34.02 c -0.688,0.386 -1.293,0.339 -1.664,-0.051 L 26.32,24 l 3.379,3.379 z"
|
||||
style="fill:url(#linearGradient92);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path104"
|
||||
inkscape:connector-curvature="0" /></g><g
|
||||
id="g106"><g
|
||||
id="g108" /><g
|
||||
id="g122"
|
||||
mask="url(#mask114)"><g
|
||||
id="g124" /><g
|
||||
id="g146"><g
|
||||
clip-path="url(#clipPath126)"
|
||||
id="g148"><g
|
||||
id="g150"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:url(#pattern134);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path152"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></g><g
|
||||
id="g154"><g
|
||||
id="g156" /><g
|
||||
id="g170"
|
||||
mask="url(#mask162)"><g
|
||||
id="g172" /><g
|
||||
id="g194"><g
|
||||
clip-path="url(#clipPath174)"
|
||||
id="g196"><g
|
||||
id="g198"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:url(#pattern182);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path200"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></g><g
|
||||
id="g202"><g
|
||||
id="g204" /><g
|
||||
id="g218"
|
||||
mask="url(#mask210)"><g
|
||||
id="g220" /><g
|
||||
id="g242"><g
|
||||
clip-path="url(#clipPath222)"
|
||||
id="g244"><g
|
||||
id="g246"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:url(#pattern230);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path248"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></g><g
|
||||
id="g250"><g
|
||||
id="g252" /><g
|
||||
id="g266"
|
||||
mask="url(#mask258)"><g
|
||||
id="g268" /><g
|
||||
id="g290"><g
|
||||
clip-path="url(#clipPath270)"
|
||||
id="g292"><g
|
||||
id="g294"><path
|
||||
d="M 0,0 124,0 124,48 0,48 0,0 Z"
|
||||
style="fill:url(#pattern278);fill-opacity:1;fill-rule:nonzero;stroke:none"
|
||||
id="path296"
|
||||
inkscape:connector-curvature="0" /></g></g></g></g></g></g></g></svg>
|
After Width: | Height: | Size: 22 KiB |
|
@ -3,8 +3,6 @@ import { createStyles, Theme } from "@material-ui/core";
|
|||
const styles = createStyles((theme: Theme) => ({
|
||||
messageOuter: {
|
||||
position: 'relative',
|
||||
paddingTop: theme.spacing.unit * 2,
|
||||
paddingBottom: theme.spacing.unit,
|
||||
},
|
||||
messageInner: {
|
||||
width: '100%',
|
||||
|
|
|
@ -2,13 +2,13 @@ import { createStyles, Theme } from "@material-ui/core";
|
|||
|
||||
const styles = createStyles((theme: Theme) => ({
|
||||
form: {
|
||||
padding: '20px 0px',
|
||||
paddingTop: theme.spacing.unit * 2,
|
||||
},
|
||||
field: {
|
||||
width: '100%',
|
||||
},
|
||||
button: {
|
||||
marginTop: '20px',
|
||||
marginTop: theme.spacing.unit * 2,
|
||||
width: '100%',
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -1,14 +1,54 @@
|
|||
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,
|
||||
},
|
||||
textField: {
|
||||
width: '100%',
|
||||
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',
|
||||
},
|
||||
}));
|
||||
|
||||
|
|
|
@ -2,15 +2,13 @@ import { createStyles, Theme } from "@material-ui/core";
|
|||
|
||||
const styles = createStyles((theme: Theme) => ({
|
||||
form: {
|
||||
paddingTop: theme.spacing.unit * 2,
|
||||
paddingBottom: theme.spacing.unit * 2,
|
||||
marginTop: theme.spacing.unit * 2,
|
||||
},
|
||||
field: {
|
||||
width: '100%',
|
||||
marginBottom: theme.spacing.unit * 2,
|
||||
},
|
||||
button: {
|
||||
marginTop: theme.spacing.unit * 2,
|
||||
width: '100%',
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -25,12 +25,25 @@ const styles = createStyles((theme: Theme) => ({
|
|||
body: {
|
||||
paddingTop: theme.spacing.unit * 2,
|
||||
paddingBottom: theme.spacing.unit * 2,
|
||||
paddingLeft: theme.spacing.unit,
|
||||
paddingRight: theme.spacing.unit,
|
||||
paddingLeft: theme.spacing.unit * 2,
|
||||
paddingRight: theme.spacing.unit * 2,
|
||||
border: '1px solid #e0e0e0',
|
||||
borderRadius: '2px',
|
||||
textAlign: 'justify',
|
||||
},
|
||||
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',
|
||||
},
|
||||
|
@ -39,19 +52,17 @@ const styles = createStyles((theme: Theme) => ({
|
|||
marginTop: theme.spacing.unit * 2,
|
||||
marginBottom: theme.spacing.unit * 2,
|
||||
},
|
||||
footer: {
|
||||
paddingTop: theme.spacing.unit,
|
||||
fontSize: theme.typography.fontSize * 0.9,
|
||||
},
|
||||
registerDevice: {
|
||||
float: 'right',
|
||||
registerDeviceContainer: {
|
||||
textAlign: 'right',
|
||||
fontSize: theme.typography.fontSize * 0.8,
|
||||
},
|
||||
registerDevice: {},
|
||||
totpField: {
|
||||
marginTop: theme.spacing.unit * 2,
|
||||
marginBottom: theme.spacing.unit * 2,
|
||||
width: '100%',
|
||||
},
|
||||
totpButton: {
|
||||
marginTop: theme.spacing.unit * 2,
|
||||
width: '100%',
|
||||
}
|
||||
}));
|
||||
|
|
|
@ -10,6 +10,10 @@ const styles = createStyles((theme: Theme) => ({
|
|||
width: '120px',
|
||||
},
|
||||
},
|
||||
retryButtonContainer: {
|
||||
textAlign: 'center',
|
||||
paddingTop: theme.spacing.unit * 2,
|
||||
},
|
||||
}));
|
||||
|
||||
export default styles;
|
|
@ -0,0 +1,148 @@
|
|||
$brand-success: #5cb85c;
|
||||
$brand-failure: #d44141;
|
||||
$loader-size: 4em;
|
||||
$check-height: $loader-size/2;
|
||||
$check-width: $check-height/2;
|
||||
$check-left: ($loader-size/6 + $loader-size/25);
|
||||
$check-thickness: 3px;
|
||||
$check-color: $brand-success;
|
||||
|
||||
$cross-height: $loader-size/2;
|
||||
$cross-width: $check-height/10 - $check-height/12;
|
||||
$cross-left: $loader-size/2;
|
||||
$cross-top: $loader-size/4;
|
||||
|
||||
.circleLoader {
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-left-color: $check-color;
|
||||
animation: loader-spin 1.2s infinite linear;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
border-radius: 50%;
|
||||
width: $loader-size;
|
||||
height: $loader-size;
|
||||
}
|
||||
|
||||
.loadComplete {
|
||||
-webkit-animation: none;
|
||||
animation: none;
|
||||
transition: border 500ms ease-out;
|
||||
&.success {
|
||||
border-color: $brand-success;
|
||||
}
|
||||
&.failure {
|
||||
border-color: $brand-failure;
|
||||
}
|
||||
}
|
||||
|
||||
.checkmark {
|
||||
display: none;
|
||||
|
||||
&.show {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
&.draw:after {
|
||||
animation-duration: 800ms;
|
||||
animation-timing-function: ease;
|
||||
animation-name: checkmark;
|
||||
transform: scaleX(-1) rotate(135deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
opacity: 1;
|
||||
height: $check-height;
|
||||
width: $check-width;
|
||||
transform-origin: left top;
|
||||
border-right: $check-thickness solid $check-color;
|
||||
border-top: $check-thickness solid $check-color;
|
||||
content: '';
|
||||
left: $check-left;
|
||||
top: $check-height;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.cross {
|
||||
display: none;
|
||||
|
||||
&.show {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
&.draw:after, &.draw:before {
|
||||
animation-duration: 300ms;
|
||||
animation-timing-function: ease;
|
||||
animation-name: cross;
|
||||
}
|
||||
|
||||
&:before, &:after {
|
||||
position: absolute;
|
||||
left: $cross-left;
|
||||
top: $cross-top;
|
||||
content: '';
|
||||
height: $cross-height;
|
||||
width: $cross-width;
|
||||
background-color: $brand-failure;
|
||||
}
|
||||
|
||||
&:before {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
&:after {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes loader-spin {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes checkmark {
|
||||
0% {
|
||||
height: 0;
|
||||
width: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
20% {
|
||||
height: 0;
|
||||
width: $check-width;
|
||||
opacity: 1;
|
||||
}
|
||||
40% {
|
||||
height: $check-height;
|
||||
width: $check-width;
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
height: $check-height;
|
||||
width: $check-width;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes cross {
|
||||
0% {
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
20% {
|
||||
height: 0;
|
||||
width: $cross-width;
|
||||
}
|
||||
40% {
|
||||
height: $cross-height;
|
||||
width: $cross-width;
|
||||
}
|
||||
100% {
|
||||
width: $cross-width;
|
||||
height: $cross-height;
|
||||
}
|
||||
}
|
44
client-react/src/components/CircleLoader/CircleLoader.tsx
Normal file
44
client-react/src/components/CircleLoader/CircleLoader.tsx
Normal file
|
@ -0,0 +1,44 @@
|
|||
import React, { Component } from "react";
|
||||
import classnames from 'classnames';
|
||||
|
||||
import styles from './CircleLoader.module.scss';
|
||||
|
||||
export enum Status {
|
||||
LOADING,
|
||||
SUCCESSFUL,
|
||||
FAILURE,
|
||||
}
|
||||
|
||||
export interface Props {
|
||||
status: Status;
|
||||
}
|
||||
|
||||
class CircleLoader extends Component<Props> {
|
||||
render() {
|
||||
const containerClasses = [styles.circleLoader];
|
||||
const checkmarkClasses = [styles.checkmark, styles.draw];
|
||||
const crossClasses = [styles.cross, styles.draw];
|
||||
|
||||
if (this.props.status === Status.SUCCESSFUL) {
|
||||
containerClasses.push(styles.loadComplete);
|
||||
containerClasses.push(styles.success);
|
||||
checkmarkClasses.push(styles.show);
|
||||
}
|
||||
else if (this.props.status === Status.FAILURE) {
|
||||
containerClasses.push(styles.loadComplete);
|
||||
containerClasses.push(styles.failure);
|
||||
crossClasses.push(styles.show);
|
||||
}
|
||||
|
||||
const key = 'container-' + this.props.status;
|
||||
|
||||
return (
|
||||
<div className={classnames(containerClasses)} key={key}>
|
||||
{<div className={classnames(checkmarkClasses)} />}
|
||||
{<div className={classnames(crossClasses)} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default CircleLoader;
|
|
@ -1,14 +1,14 @@
|
|||
import { connect } from 'react-redux';
|
||||
import StateSynchronizer, { OnLoaded, OnError } from '../../../components/StateSynchronizer/StateSynchronizer';
|
||||
import { RootState } from '../../../reducers';
|
||||
import { fetchStateSuccess, fetchState, fetchStateFailure } from '../../../reducers/Portal/actions';
|
||||
import { fetchStateSuccess, fetchState, fetchStateFailure } from '../../../reducers/Portal/FirstFactor/actions';
|
||||
import RemoteState from '../../../reducers/Portal/RemoteState';
|
||||
import { Dispatch } from 'redux';
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
state: state.remoteState,
|
||||
stateError: state.remoteStateError,
|
||||
stateLoading: state.remoteStateLoading,
|
||||
state: state.firstFactor.remoteState,
|
||||
stateError: state.firstFactor.remoteStateError,
|
||||
stateLoading: state.firstFactor.remoteStateLoading,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => {
|
||||
|
|
|
@ -3,7 +3,7 @@ import PortalLayout from '../../../layouts/PortalLayout/PortalLayout';
|
|||
import { RootState } from '../../../reducers';
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
authenticationLevel: (state.remoteState) ? state.remoteState.authentication_level : 0,
|
||||
authenticationLevel: (state.firstFactor.remoteState) ? state.firstFactor.remoteState.authentication_level : 0,
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(PortalLayout);
|
|
@ -1,12 +1,28 @@
|
|||
import { connect } from 'react-redux';
|
||||
import QueryString from 'query-string';
|
||||
import FirstFactorView, { Props } from '../../../views/FirstFactorView/FirstFactorView';
|
||||
import { Dispatch } from 'redux';
|
||||
import { authenticateFailure, authenticateSuccess, authenticate } from '../../../reducers/Portal/actions';
|
||||
import { authenticateFailure, authenticateSuccess, authenticate } from '../../../reducers/Portal/FirstFactor/actions';
|
||||
import { RootState } from '../../../reducers';
|
||||
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({});
|
||||
|
||||
function redirect2FA(props: Props) {
|
||||
if (!props.location) {
|
||||
props.history.push('/2fa');
|
||||
return;
|
||||
}
|
||||
const params = QueryString.parse(props.location.search);
|
||||
|
||||
if ('rd' in params) {
|
||||
const rd = params['rd'] as string;
|
||||
props.history.push(`/2fa?rd=${rd}`);
|
||||
return;
|
||||
}
|
||||
props.history.push('/2fa');
|
||||
}
|
||||
|
||||
function onAuthenticationRequested(dispatch: Dispatch, ownProps: Props) {
|
||||
return async (username: string, password: string) => {
|
||||
dispatch(authenticate());
|
||||
|
@ -27,7 +43,7 @@ function onAuthenticationRequested(dispatch: Dispatch, ownProps: Props) {
|
|||
return;
|
||||
}
|
||||
dispatch(authenticateSuccess());
|
||||
ownProps.history.push('/2fa');
|
||||
redirect2FA(ownProps);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
import { connect } from 'react-redux';
|
||||
import OneTimePasswordRegistrationView, { OnSuccess, OnFailure } from '../../../views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView';
|
||||
import OneTimePasswordRegistrationView from '../../../views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView';
|
||||
import { RootState } from '../../../reducers';
|
||||
import { Dispatch } from 'redux';
|
||||
import {to} from 'await-to-js';
|
||||
import { generateTotpSecret, generateTotpSecretSuccess, generateTotpSecretFailure } from '../../../reducers/Portal/OneTimePasswordRegistration/actions';
|
||||
import { Props } from '../../../views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView';
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({});
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
error: state.oneTimePasswordRegistration.error,
|
||||
secret: state.oneTimePasswordRegistration.secret,
|
||||
});
|
||||
|
||||
async function checkIdentity(token: string) {
|
||||
return fetch(`/api/secondfactor/totp/identity/finish?token=${token}`, {
|
||||
|
@ -27,16 +32,35 @@ async function checkIdentity(token: string) {
|
|||
});
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => {
|
||||
async function tryGenerateTotpSecret(dispatch: Dispatch, token: string) {
|
||||
let err, result;
|
||||
dispatch(generateTotpSecret());
|
||||
[err, result] = await to(checkIdentity(token));
|
||||
if (err) {
|
||||
const e = err;
|
||||
setTimeout(() => {
|
||||
dispatch(generateTotpSecretFailure(e.message));
|
||||
}, 2000);
|
||||
return;
|
||||
}
|
||||
dispatch(generateTotpSecretSuccess(result));
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => {
|
||||
let internalToken: string;
|
||||
return {
|
||||
componentDidMount: async (token: string, onSuccess: OnSuccess, onFailure: OnFailure) => {
|
||||
let err, result;
|
||||
[err, result] = await to(checkIdentity(token));
|
||||
if (err) {
|
||||
onFailure(err);
|
||||
return;
|
||||
}
|
||||
onSuccess(result.otpauth_url);
|
||||
onInit: async (token: string) => {
|
||||
internalToken = token;
|
||||
await tryGenerateTotpSecret(dispatch, internalToken);
|
||||
},
|
||||
onRetryClicked: async () => {
|
||||
await tryGenerateTotpSecret(dispatch, internalToken);
|
||||
},
|
||||
onCancelClicked: () => {
|
||||
ownProps.history.push('/2fa');
|
||||
},
|
||||
onLoginClicked: () => {
|
||||
ownProps.history.push('/2fa');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import { connect } from 'react-redux';
|
||||
import QueryString from 'query-string';
|
||||
import SecondFactorView, {Props} from '../../../views/SecondFactorView/SecondFactorView';
|
||||
import { RootState } from '../../../reducers';
|
||||
import { Dispatch } from 'redux';
|
||||
import u2fApi, { SignResponse } from 'u2f-api';
|
||||
import to from 'await-to-js';
|
||||
import { logoutSuccess, logoutFailure, logout } from '../../../reducers/Portal/actions';
|
||||
import { logoutSuccess, logoutFailure, logout, securityKeySignSuccess, securityKeySign, securityKeySignFailure, setSecurityKeySupported } from '../../../reducers/Portal/SecondFactor/actions';
|
||||
import AuthenticationLevel from '../../../types/AuthenticationLevel';
|
||||
import RemoteState from '../../../reducers/Portal/RemoteState';
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
state: state.remoteState,
|
||||
stateError: state.remoteStateError,
|
||||
state: state.firstFactor.remoteState,
|
||||
stateError: state.firstFactor.remoteStateError,
|
||||
securityKeySupported: state.secondFactor.securityKeySupported,
|
||||
securityKeyVerified: state.secondFactor.securityKeySignSuccess || false,
|
||||
securityKeyError: state.secondFactor.error,
|
||||
});
|
||||
|
||||
async function requestSigning() {
|
||||
|
@ -23,7 +27,7 @@ async function requestSigning() {
|
|||
});
|
||||
}
|
||||
|
||||
async function completeSigning(response: u2fApi.SignResponse) {
|
||||
async function completeSecurityKeySigning(response: u2fApi.SignResponse) {
|
||||
return fetch('/api/u2f/sign', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
|
@ -39,25 +43,37 @@ async function completeSigning(response: u2fApi.SignResponse) {
|
|||
});
|
||||
}
|
||||
|
||||
async function triggerSecurityKeySigning() {
|
||||
async function triggerSecurityKeySigning(dispatch: Dispatch, props: Props) {
|
||||
let err, result;
|
||||
dispatch(securityKeySign());
|
||||
[err, result] = await to(requestSigning());
|
||||
if (err) {
|
||||
console.error(err);
|
||||
dispatch(securityKeySignFailure(err.message));
|
||||
return;
|
||||
}
|
||||
|
||||
[err, result] = await to(u2fApi.sign(result, 60));
|
||||
if (err) {
|
||||
console.error(err);
|
||||
dispatch(securityKeySignFailure(err.message));
|
||||
return;
|
||||
}
|
||||
|
||||
[err, result] = await to(completeSigning(result as SignResponse));
|
||||
[err, result] = await to(completeSecurityKeySigning(result as SignResponse));
|
||||
if (err) {
|
||||
console.error(err);
|
||||
dispatch(securityKeySignFailure(err.message));
|
||||
return;
|
||||
}
|
||||
dispatch(securityKeySignSuccess());
|
||||
await redirectUponAuthentication(props);
|
||||
}
|
||||
|
||||
async function redirectUponAuthentication(props: Props) {
|
||||
const params = QueryString.parse(props.history.location.search);
|
||||
if ('rd' in params) {
|
||||
setTimeout(() => {
|
||||
window.location.replace(params['rd'] as string);
|
||||
}, 1500);
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => {
|
||||
|
@ -108,7 +124,11 @@ const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => {
|
|||
ownProps.history.push('/');
|
||||
return;
|
||||
}
|
||||
await triggerSecurityKeySigning();
|
||||
const isU2FSupported = await u2fApi.isSupported();
|
||||
if (isU2FSupported) {
|
||||
await dispatch(setSecurityKeySupported(true));
|
||||
await triggerSecurityKeySigning(dispatch, ownProps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,13 @@ import { RootState } from '../../../reducers';
|
|||
import { Dispatch } from 'redux';
|
||||
import {to} from 'await-to-js';
|
||||
import * as U2fApi from "u2f-api";
|
||||
import { Props } from '../../../views/SecurityKeyRegistrationView/SecurityKeyRegistrationView';
|
||||
import { registerSecurityKey, registerSecurityKeyFailure, registerSecurityKeySuccess } from '../../../reducers/Portal/SecurityKeyRegistration/actions';
|
||||
|
||||
const mapStateToProps = (state: RootState) => ({});
|
||||
const mapStateToProps = (state: RootState) => ({
|
||||
deviceRegistered: state.securityKeyRegistration.success,
|
||||
error: state.securityKeyRegistration.error,
|
||||
});
|
||||
|
||||
async function checkIdentity(token: string) {
|
||||
return fetch(`/api/secondfactor/u2f/identity/finish?token=${token}`, {
|
||||
|
@ -39,32 +44,45 @@ async function completeRegistration(response: U2fApi.RegisterResponse) {
|
|||
});
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch) => {
|
||||
function fail(dispatch: Dispatch, err: Error) {
|
||||
dispatch(registerSecurityKeyFailure(err.message));
|
||||
}
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch, ownProps: Props) => {
|
||||
return {
|
||||
componentDidMount: async (token: string) => {
|
||||
onInit: async (token: string) => {
|
||||
let err, result;
|
||||
dispatch(registerSecurityKey());
|
||||
[err, result] = await to(checkIdentity(token));
|
||||
if (err) {
|
||||
console.error(err);
|
||||
fail(dispatch, err);
|
||||
return;
|
||||
}
|
||||
[err, result] = await to(requestRegistration());
|
||||
if (err) {
|
||||
console.error(err);
|
||||
fail(dispatch, err);
|
||||
return;
|
||||
}
|
||||
|
||||
[err, result] = await to(U2fApi.register(result, [], 60));
|
||||
if (err) {
|
||||
console.error(err);
|
||||
fail(dispatch, err);
|
||||
return;
|
||||
}
|
||||
|
||||
[err, result] = await to(completeRegistration(result as U2fApi.RegisterResponse));
|
||||
if (err) {
|
||||
console.error(err);
|
||||
fail(dispatch, err);
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(registerSecurityKeySuccess());
|
||||
setTimeout(() => {
|
||||
ownProps.history.push('/2fa');
|
||||
}, 2000);
|
||||
},
|
||||
onBackClicked: () => {
|
||||
ownProps.history.push('/2fa');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,8 @@ import {
|
|||
FETCH_STATE_REQUEST,
|
||||
FETCH_STATE_SUCCESS,
|
||||
FETCH_STATE_FAILURE,
|
||||
LOGOUT_REQUEST,
|
||||
LOGOUT_SUCCESS,
|
||||
LOGOUT_FAILURE
|
||||
} from "../constants";
|
||||
import RemoteState from './RemoteState';
|
||||
} from "../../constants";
|
||||
import RemoteState from '../RemoteState';
|
||||
|
||||
/* FETCH_STATE */
|
||||
export const fetchState = createAction(FETCH_STATE_REQUEST);
|
||||
|
@ -31,11 +28,3 @@ export const authenticateSuccess = createAction(AUTHENTICATE_SUCCESS);
|
|||
export const authenticateFailure = createAction(AUTHENTICATE_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
});
|
||||
|
||||
|
||||
/* AUTHENTICATE_REQUEST */
|
||||
export const logout = createAction(LOGOUT_REQUEST);
|
||||
export const logoutSuccess = createAction(LOGOUT_SUCCESS);
|
||||
export const logoutFailure = createAction(LOGOUT_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
import * as Actions from './actions';
|
||||
import { ActionType, getType, StateType } from 'typesafe-actions';
|
||||
import RemoteState from './RemoteState';
|
||||
import RemoteState from '../RemoteState';
|
||||
|
||||
export type FirstFactorAction = ActionType<typeof Actions>;
|
||||
|
||||
|
@ -19,10 +19,6 @@ interface State {
|
|||
remoteState: RemoteState | null;
|
||||
remoteStateLoading: boolean;
|
||||
remoteStateError: string | null;
|
||||
|
||||
logoutLoading: boolean;
|
||||
logoutSuccess: boolean | null;
|
||||
logoutError: string | null;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
|
@ -32,9 +28,6 @@ const initialState: State = {
|
|||
remoteState: null,
|
||||
remoteStateLoading: false,
|
||||
remoteStateError: null,
|
||||
logoutLoading: false,
|
||||
logoutError: null,
|
||||
logoutSuccess: null,
|
||||
}
|
||||
|
||||
export type PortalState = StateType<State>;
|
||||
|
@ -81,26 +74,6 @@ export default (state = initialState, action: FirstFactorAction) => {
|
|||
remoteStateError: action.payload,
|
||||
remoteStateLoading: false,
|
||||
};
|
||||
|
||||
case getType(Actions.logout):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: true,
|
||||
logoutSuccess: null,
|
||||
logoutError: null,
|
||||
};
|
||||
case getType(Actions.logoutSuccess):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: false,
|
||||
logoutSuccess: true,
|
||||
};
|
||||
case getType(Actions.logoutFailure):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: false,
|
||||
logoutError: action.payload,
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
import { createAction } from "typesafe-actions";
|
||||
import { GENERATE_TOTP_SECRET_REQUEST, GENERATE_TOTP_SECRET_SUCCESS, GENERATE_TOTP_SECRET_FAILURE } from "../../constants";
|
||||
import { Secret } from "../../../views/OneTimePasswordRegistrationView/Secret";
|
||||
|
||||
|
||||
/* GENERATE_TOTP_SECRET_REQUEST */
|
||||
export const generateTotpSecret = createAction(GENERATE_TOTP_SECRET_REQUEST);
|
||||
export const generateTotpSecretSuccess = createAction(GENERATE_TOTP_SECRET_SUCCESS, resolve => {
|
||||
return (secret: Secret) => resolve(secret);
|
||||
});
|
||||
export const generateTotpSecretFailure = createAction(GENERATE_TOTP_SECRET_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
});
|
|
@ -0,0 +1,50 @@
|
|||
import { ActionType, getType } from "typesafe-actions";
|
||||
import * as Actions from './actions';
|
||||
import { Secret } from "../../../views/OneTimePasswordRegistrationView/Secret";
|
||||
|
||||
type OneTimePasswordRegistrationAction = ActionType<typeof Actions>
|
||||
|
||||
export interface State {
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
secret: Secret | null;
|
||||
}
|
||||
|
||||
let initialState: State = {
|
||||
loading: true,
|
||||
error: null,
|
||||
secret: null,
|
||||
}
|
||||
|
||||
initialState = {
|
||||
secret: {
|
||||
base32_secret: 'PBSFWU2RM42HG3TNIRHUQMKSKVUW6NCNOBNFOLCFJZATS6CTI47A',
|
||||
otpauth_url: 'PBSFWU2RM42HG3TNIRHUQMKSKVUW6NCNOBNFOLCFJZATS6CTI47A',
|
||||
},
|
||||
error: null,
|
||||
loading: false,
|
||||
}
|
||||
|
||||
export default (state = initialState, action: OneTimePasswordRegistrationAction) => {
|
||||
switch(action.type) {
|
||||
case getType(Actions.generateTotpSecret):
|
||||
return {
|
||||
loading: true,
|
||||
error: null,
|
||||
secret: null,
|
||||
};
|
||||
case getType(Actions.generateTotpSecretSuccess):
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
secret: action.payload,
|
||||
}
|
||||
case getType(Actions.generateTotpSecretFailure):
|
||||
return {
|
||||
...state,
|
||||
loading: false,
|
||||
error: action.payload,
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
26
client-react/src/reducers/Portal/SecondFactor/actions.ts
Normal file
26
client-react/src/reducers/Portal/SecondFactor/actions.ts
Normal file
|
@ -0,0 +1,26 @@
|
|||
import { createAction } from "typesafe-actions";
|
||||
import {
|
||||
LOGOUT_REQUEST,
|
||||
LOGOUT_SUCCESS,
|
||||
LOGOUT_FAILURE,
|
||||
SECURITY_KEY_SIGN,
|
||||
SECURITY_KEY_SIGN_SUCCESS,
|
||||
SECURITY_KEY_SIGN_FAILURE,
|
||||
SET_SECURITY_KEY_SUPPORTED
|
||||
} from "../../constants";
|
||||
|
||||
export const setSecurityKeySupported = createAction(SET_SECURITY_KEY_SUPPORTED, resolve => {
|
||||
return (supported: boolean) => resolve(supported);
|
||||
})
|
||||
|
||||
export const securityKeySign = createAction(SECURITY_KEY_SIGN);
|
||||
export const securityKeySignSuccess = createAction(SECURITY_KEY_SIGN_SUCCESS);
|
||||
export const securityKeySignFailure = createAction(SECURITY_KEY_SIGN_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
})
|
||||
|
||||
export const logout = createAction(LOGOUT_REQUEST);
|
||||
export const logoutSuccess = createAction(LOGOUT_SUCCESS);
|
||||
export const logoutFailure = createAction(LOGOUT_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
});
|
75
client-react/src/reducers/Portal/SecondFactor/reducer.ts
Normal file
75
client-react/src/reducers/Portal/SecondFactor/reducer.ts
Normal file
|
@ -0,0 +1,75 @@
|
|||
|
||||
import * as Actions from './actions';
|
||||
import { ActionType, getType, StateType } from 'typesafe-actions';
|
||||
|
||||
export type SecondFactorAction = ActionType<typeof Actions>;
|
||||
|
||||
interface State {
|
||||
logoutLoading: boolean;
|
||||
logoutSuccess: boolean | null;
|
||||
error: string | null;
|
||||
|
||||
securityKeySupported: boolean;
|
||||
securityKeySignLoading: boolean;
|
||||
securityKeySignSuccess: boolean | null;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
logoutLoading: false,
|
||||
logoutSuccess: null,
|
||||
error: null,
|
||||
|
||||
securityKeySupported: false,
|
||||
securityKeySignLoading: false,
|
||||
securityKeySignSuccess: null,
|
||||
}
|
||||
|
||||
export type PortalState = StateType<State>;
|
||||
|
||||
export default (state = initialState, action: SecondFactorAction): State => {
|
||||
switch(action.type) {
|
||||
case getType(Actions.logout):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: true,
|
||||
logoutSuccess: null,
|
||||
error: null,
|
||||
};
|
||||
case getType(Actions.logoutSuccess):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: false,
|
||||
logoutSuccess: true,
|
||||
};
|
||||
case getType(Actions.logoutFailure):
|
||||
return {
|
||||
...state,
|
||||
logoutLoading: false,
|
||||
error: action.payload,
|
||||
}
|
||||
case getType(Actions.securityKeySign):
|
||||
return {
|
||||
...state,
|
||||
securityKeySignLoading: true,
|
||||
securityKeySignSuccess: false,
|
||||
};
|
||||
case getType(Actions.securityKeySignSuccess):
|
||||
return {
|
||||
...state,
|
||||
securityKeySignLoading: false,
|
||||
securityKeySignSuccess: true,
|
||||
};
|
||||
case getType(Actions.securityKeySignFailure):
|
||||
return {
|
||||
...state,
|
||||
securityKeySignLoading: false,
|
||||
securityKeySignSuccess: false,
|
||||
};
|
||||
case getType(Actions.setSecurityKeySupported):
|
||||
return {
|
||||
...state,
|
||||
securityKeySupported: action.payload,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
import { createAction } from "typesafe-actions";
|
||||
import { REGISTER_SECURITY_KEY_REQUEST, REGISTER_SECURITY_KEY_SUCCESS, REGISTER_SECURITY_KEY_FAILURE } from "../../constants";
|
||||
|
||||
export const registerSecurityKey = createAction(REGISTER_SECURITY_KEY_REQUEST);
|
||||
export const registerSecurityKeySuccess = createAction(REGISTER_SECURITY_KEY_SUCCESS);
|
||||
export const registerSecurityKeyFailure = createAction(REGISTER_SECURITY_KEY_FAILURE, resolve => {
|
||||
return (error: string) => resolve(error);
|
||||
});
|
|
@ -0,0 +1,36 @@
|
|||
import { ActionType, getType } from "typesafe-actions";
|
||||
import * as Actions from './actions';
|
||||
|
||||
type SecurityKeyRegistrationAction = ActionType<typeof Actions>
|
||||
|
||||
export interface State {
|
||||
error: string | null;
|
||||
success: boolean | null;
|
||||
}
|
||||
|
||||
let initialState: State = {
|
||||
error: null,
|
||||
success: null,
|
||||
}
|
||||
|
||||
export default (state = initialState, action: SecurityKeyRegistrationAction): State => {
|
||||
switch(action.type) {
|
||||
case getType(Actions.registerSecurityKey):
|
||||
return {
|
||||
success: null,
|
||||
error: null,
|
||||
};
|
||||
case getType(Actions.registerSecurityKeySuccess):
|
||||
return {
|
||||
...state,
|
||||
success: true,
|
||||
};
|
||||
case getType(Actions.registerSecurityKeyFailure):
|
||||
return {
|
||||
...state,
|
||||
success: false,
|
||||
error: action.payload,
|
||||
};
|
||||
}
|
||||
return state;
|
||||
}
|
13
client-react/src/reducers/Portal/index.ts
Normal file
13
client-react/src/reducers/Portal/index.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { combineReducers } from 'redux';
|
||||
|
||||
import FirstFactorReducer from './FirstFactor/reducer';
|
||||
import SecondFactorReducer from './SecondFactor/reducer';
|
||||
import OneTimePasswordRegistrationReducer from './OneTimePasswordRegistration/reducer';
|
||||
import SecurityKeyRegistrationReducer from './SecurityKeyRegistration/reducer';
|
||||
|
||||
export default combineReducers({
|
||||
firstFactor: FirstFactorReducer,
|
||||
secondFactor: SecondFactorReducer,
|
||||
oneTimePasswordRegistration: OneTimePasswordRegistrationReducer,
|
||||
securityKeyRegistration: SecurityKeyRegistrationReducer,
|
||||
});
|
|
@ -7,6 +7,23 @@ export const AUTHENTICATE_REQUEST = '@portal/authenticate_request';
|
|||
export const AUTHENTICATE_SUCCESS = '@portal/authenticate_success';
|
||||
export const AUTHENTICATE_FAILURE = '@portal/authenticate_failure';
|
||||
|
||||
// SECOND FACTOR PAGE
|
||||
export const SET_SECURITY_KEY_SUPPORTED = '@portal/second_factor/set_security_key_supported';
|
||||
|
||||
export const SECURITY_KEY_SIGN = '@portal/second_factor/security_key_sign';
|
||||
export const SECURITY_KEY_SIGN_SUCCESS = '@portal/second_factor/security_key_sign_success';
|
||||
export const SECURITY_KEY_SIGN_FAILURE = '@portal/second_factor/security_key_sign_failure';
|
||||
|
||||
export const LOGOUT_REQUEST = '@portal/logout_request';
|
||||
export const LOGOUT_SUCCESS = '@portal/logout_success';
|
||||
export const LOGOUT_FAILURE = '@portal/logout_failure';
|
||||
|
||||
// TOTP REGISTRATION
|
||||
export const GENERATE_TOTP_SECRET_REQUEST = '@portal/generate_totp_secret_request';
|
||||
export const GENERATE_TOTP_SECRET_SUCCESS = '@portal/generate_totp_secret_success';
|
||||
export const GENERATE_TOTP_SECRET_FAILURE = '@portal/generate_totp_secret_failure';
|
||||
|
||||
// U2F REGISTRATION
|
||||
export const REGISTER_SECURITY_KEY_REQUEST = '@portal/security_key_registration/register_request';
|
||||
export const REGISTER_SECURITY_KEY_SUCCESS = '@portal/security_key_registration/register_success';
|
||||
export const REGISTER_SECURITY_KEY_FAILURE = '@portal/security_key_registration/register_failed';
|
|
@ -1,5 +1,6 @@
|
|||
import PortalReducer, { PortalState } from './Portal/reducer';
|
||||
import PortalReducer from './Portal';
|
||||
import { StateType } from 'typesafe-actions';
|
||||
|
||||
export type RootState = PortalState;
|
||||
export type RootState = StateType<typeof PortalReducer>;
|
||||
|
||||
export default PortalReducer;
|
|
@ -7,7 +7,7 @@ import FormControlLabel from '@material-ui/core/FormControlLabel';
|
|||
import Checkbox from '@material-ui/core/Checkbox';
|
||||
|
||||
import { Link } from "react-router-dom";
|
||||
import { RouterProps } from "react-router";
|
||||
import { RouterProps, RouteProps } from "react-router";
|
||||
import { WithStyles, withStyles } from "@material-ui/core";
|
||||
|
||||
import firstFactorViewStyles from '../../assets/jss/views/FirstFactorView/FirstFactorView';
|
||||
|
@ -18,7 +18,7 @@ import CheckBoxIcon from '@material-ui/icons/CheckBox';
|
|||
import StateSynchronizer from "../../containers/components/StateSynchronizer/StateSynchronizer";
|
||||
import RemoteState from "../../reducers/Portal/RemoteState";
|
||||
|
||||
export interface Props extends RouterProps, WithStyles {
|
||||
export interface Props extends RouteProps, RouterProps, WithStyles {
|
||||
onAuthenticationRequested(username: string, password: string): void;
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ class FirstFactorView extends Component<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
private renderWithState(state: RemoteState) {
|
||||
private renderWithState() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
|
@ -137,7 +137,7 @@ class FirstFactorView extends Component<Props, State> {
|
|||
<div>
|
||||
<StateSynchronizer
|
||||
onLoaded={(remoteState) => this.setState({remoteState})}/>
|
||||
{this.state.remoteState ? this.renderWithState(this.state.remoteState) : null}
|
||||
{this.state.remoteState ? this.renderWithState() : null}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -156,10 +156,6 @@ class FirstFactorView extends Component<Props, State> {
|
|||
errorMessage: 'An error occured. Your username/password are probably wrong.'
|
||||
});
|
||||
}
|
||||
|
||||
onSuccess = () => {
|
||||
this.props.history.push('/2fa');
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(firstFactorViewStyles)(FirstFactorView);
|
|
@ -20,7 +20,7 @@ class ForgotPasswordView extends Component<Props> {
|
|||
label="E-mail">
|
||||
</TextField>
|
||||
<Button
|
||||
onClick={() => this.props.history.push('/reset-password')}
|
||||
onClick={() => this.props.history.push('/confirmation-sent')}
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.button}>
|
||||
|
|
|
@ -1,40 +1,38 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
import { WithStyles, withStyles, TextField } from "@material-ui/core";
|
||||
import { WithStyles, withStyles, CircularProgress, Button } from "@material-ui/core";
|
||||
|
||||
import styles from '../../assets/jss/views/OneTimePasswordRegistrationView/OneTimePasswordRegistrationView';
|
||||
import { RouteProps } from "react-router";
|
||||
import { RouteProps, RouterProps } from "react-router";
|
||||
import QueryString from 'query-string';
|
||||
|
||||
import QRCode from 'qrcode.react';
|
||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
||||
|
||||
export type OnSuccess = (secret: Secret) => void;
|
||||
export type OnFailure = (err: Error) => void;
|
||||
import googleStoreImage from '../../assets/images/googleplay-badge.svg';
|
||||
import appleStoreImage from '../../assets/images/applestore-badge.svg';
|
||||
import { Secret } from "./Secret";
|
||||
|
||||
export interface Props extends WithStyles, RouteProps {
|
||||
componentDidMount: (token: string, onSuccess: OnSuccess, onFailure: OnFailure) => void;
|
||||
}
|
||||
|
||||
export interface Secret {
|
||||
otp_url: string;
|
||||
base32_secret: string;
|
||||
}
|
||||
|
||||
interface State {
|
||||
export interface Props extends WithStyles, RouteProps, RouterProps {
|
||||
secret: Secret | null;
|
||||
error: string | null;
|
||||
onInit: (token: string) => void;
|
||||
onRetryClicked: () => void;
|
||||
onCancelClicked: () => void;
|
||||
onLoginClicked: () => void;
|
||||
}
|
||||
|
||||
class OneTimePasswordRegistrationView extends Component<Props, State> {
|
||||
class OneTimePasswordRegistrationView extends Component<Props> {
|
||||
private token: string | null;
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
secret: {
|
||||
otp_url: 'https://coucou',
|
||||
base32_secret: 'coucou',
|
||||
},
|
||||
}
|
||||
this.token = null;
|
||||
}
|
||||
componentDidMount() {
|
||||
|
||||
componentWillMount() {
|
||||
// If secret is already populated, we skip onInit (for testing purposes).
|
||||
if (this.props.secret) return;
|
||||
|
||||
if (!this.props.location) {
|
||||
console.error('There is no location to retrieve query params from...');
|
||||
return;
|
||||
|
@ -44,44 +42,87 @@ class OneTimePasswordRegistrationView extends Component<Props, State> {
|
|||
console.error('Token parameter is expected and not provided');
|
||||
return;
|
||||
}
|
||||
this.props.componentDidMount(
|
||||
params['token'] as string,
|
||||
this.onSuccess,
|
||||
this.onFailure);
|
||||
this.token = params['token'] as string;
|
||||
this.props.onInit(this.token);
|
||||
}
|
||||
|
||||
onSuccess = (secret: Secret) => {
|
||||
this.setState({secret});
|
||||
}
|
||||
|
||||
onFailure = (err: Error) => {}
|
||||
|
||||
private renderWithSecret(secret: Secret) {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.secretContainer}>
|
||||
<TextField
|
||||
id="totp-secret"
|
||||
label="Key"
|
||||
defaultValue={secret.base32_secret}
|
||||
className={classes.textField}
|
||||
margin="normal"
|
||||
InputProps={{
|
||||
readOnly: true,
|
||||
}}
|
||||
variant="outlined"
|
||||
/>
|
||||
<div className={classes.text}>
|
||||
Register your device by scanning the barcode or adding the key.
|
||||
</div>
|
||||
<div className={classes.qrcodeContainer}>
|
||||
{this.state.secret ? <QRCode value={this.state.secret.otp_url}></QRCode> : null}
|
||||
<div className={classes.secretContainer}>
|
||||
<div className={classes.qrcodeContainer}>
|
||||
<QRCode value={secret.otpauth_url} size={180} level="Q"></QRCode>
|
||||
</div>
|
||||
<div className={classes.base32Container}>{secret.base32_secret}</div>
|
||||
</div>
|
||||
<div className={classes.loginButtonContainer}>
|
||||
<Button
|
||||
color="primary"
|
||||
variant="contained"
|
||||
onClick={this.props.onLoginClicked}>
|
||||
Login
|
||||
</Button>
|
||||
</div>
|
||||
<div className={classes.needGoogleAuthenticator}>
|
||||
<div className={classes.needGoogleAuthenticatorText}>Need Google Authenticator?</div>
|
||||
<img src={appleStoreImage} className={classes.store} alt='Google Authenticator on Apple Store'/>
|
||||
<img src={googleStoreImage} className={classes.store} alt='Google Authenticator on Google Store'/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderError() {
|
||||
const {classes} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<FormNotification show={true}>
|
||||
<div>{this.props.error}</div>
|
||||
</FormNotification>
|
||||
<div className={classes.buttonContainer}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.button}
|
||||
onClick={this.props.onRetryClicked}>
|
||||
Retry
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
className={classes.button}
|
||||
onClick={this.props.onCancelClicked}>
|
||||
Cancel
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderSecret() {
|
||||
return this.props.secret
|
||||
? this.renderWithSecret(this.props.secret)
|
||||
: this.renderError();
|
||||
}
|
||||
|
||||
private renderLoading() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<div>One-Time password secret is being generated...</div>
|
||||
<div className={classes.progressContainer}><CircularProgress /></div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.state.secret ? this.renderWithSecret(this.state.secret) : null;
|
||||
return !this.props.secret && !this.props.error
|
||||
? this.renderLoading()
|
||||
: this.renderSecret();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
export interface Secret {
|
||||
otpauth_url: string;
|
||||
base32_secret: string;
|
||||
}
|
|
@ -16,12 +16,14 @@ class ResetPasswordView extends Component<Props> {
|
|||
<TextField
|
||||
className={classes.field}
|
||||
variant="outlined"
|
||||
type="password"
|
||||
id="password1"
|
||||
label="New password">
|
||||
</TextField>
|
||||
<TextField
|
||||
className={classes.field}
|
||||
variant="outlined"
|
||||
type="password"
|
||||
id="password2"
|
||||
label="Confirm password">
|
||||
</TextField>
|
||||
|
|
|
@ -3,16 +3,18 @@ import React, { Component } from 'react';
|
|||
import { WithStyles, withStyles, Button, TextField } from '@material-ui/core';
|
||||
|
||||
import styles from '../../assets/jss/views/SecondFactorView/SecondFactorView';
|
||||
import securityKeyImage from '../../assets/images/security-key-hand.png';
|
||||
import StateSynchronizer from '../../containers/components/StateSynchronizer/StateSynchronizer';
|
||||
import { RouterProps, Redirect } from 'react-router';
|
||||
import RemoteState from '../../reducers/Portal/RemoteState';
|
||||
import AuthenticationLevel from '../../types/AuthenticationLevel';
|
||||
import { WithState } from '../../components/StateSynchronizer/WithState';
|
||||
|
||||
type Mode = 'u2f' | 'totp';
|
||||
import CircleLoader, { Status } from '../../components/CircleLoader/CircleLoader';
|
||||
|
||||
export interface Props extends WithStyles, RouterProps, WithState {
|
||||
securityKeySupported: boolean;
|
||||
securityKeyVerified: boolean;
|
||||
securityKeyError: string | null;
|
||||
|
||||
onLogoutClicked: () => void;
|
||||
onRegisterSecurityKeyClicked: () => void;
|
||||
onRegisterOneTimePasswordClicked: () => void;
|
||||
|
@ -20,7 +22,6 @@ export interface Props extends WithStyles, RouterProps, WithState {
|
|||
};
|
||||
|
||||
interface State {
|
||||
mode: Mode;
|
||||
remoteState: RemoteState | null;
|
||||
}
|
||||
|
||||
|
@ -28,43 +29,53 @@ class SecondFactorView extends Component<Props, State> {
|
|||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
mode: 'u2f',
|
||||
remoteState: null,
|
||||
}
|
||||
}
|
||||
|
||||
private toggleMode = () => {
|
||||
if (this.state.mode === 'u2f') {
|
||||
this.setState({mode: 'totp'});
|
||||
} else if (this.state.mode === 'totp') {
|
||||
this.setState({mode: 'u2f'});
|
||||
}
|
||||
}
|
||||
|
||||
private renderU2f() {
|
||||
private renderU2f(n: number) {
|
||||
const { classes } = this.props;
|
||||
let u2fStatus = Status.LOADING;
|
||||
if (this.props.securityKeyVerified) {
|
||||
u2fStatus = Status.SUCCESSFUL;
|
||||
} else if (this.props.securityKeyError) {
|
||||
u2fStatus = Status.FAILURE;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.imageContainer}>
|
||||
<img src={securityKeyImage} alt='security key' className={classes.image}/>
|
||||
</div>
|
||||
<div className={classes.methodU2f} key='u2f-method'>
|
||||
<div className={classes.methodName}>Option {n} - Security Key</div>
|
||||
<div>Insert your security key into a USB port and touch the gold disk.</div>
|
||||
<div className={classes.imageContainer}>
|
||||
<CircleLoader status={u2fStatus}></CircleLoader>
|
||||
</div>
|
||||
<div className={classes.registerDeviceContainer}>
|
||||
<a className={classes.registerDevice} href="#"
|
||||
onClick={this.props.onRegisterSecurityKeyClicked}>
|
||||
Register device
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderTotp() {
|
||||
private renderTotp(n: number) {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<div>Provide a one-time password.</div>
|
||||
<div className={classes.methodTotp} key='totp-method'>
|
||||
<div className={classes.methodName}>Option {n} - One-Time Password</div>
|
||||
<TextField
|
||||
className={classes.totpField}
|
||||
name="password"
|
||||
id="password"
|
||||
variant="outlined"
|
||||
label="Password">
|
||||
label="One-Time Password">
|
||||
</TextField>
|
||||
<div className={classes.registerDeviceContainer}>
|
||||
<a className={classes.registerDevice} href="#"
|
||||
onClick={this.props.onRegisterOneTimePasswordClicked}>
|
||||
Register device
|
||||
</a>
|
||||
</div>
|
||||
<Button
|
||||
className={classes.totpButton}
|
||||
variant="contained"
|
||||
|
@ -76,20 +87,20 @@ class SecondFactorView extends Component<Props, State> {
|
|||
}
|
||||
|
||||
private renderMode() {
|
||||
if (this.state.mode === 'u2f') {
|
||||
return this.renderU2f();
|
||||
} else if (this.state.mode === 'totp') {
|
||||
return this.renderTotp();
|
||||
const { classes } = this.props;
|
||||
const methods = [];
|
||||
let n = 1;
|
||||
if (this.props.securityKeySupported) {
|
||||
methods.push(this.renderU2f(n));
|
||||
n++;
|
||||
}
|
||||
}
|
||||
methods.push(this.renderTotp(n));
|
||||
|
||||
private onRegisterClicked = () => {
|
||||
const mode = this.state.mode;
|
||||
if (mode === 'u2f') {
|
||||
this.props.onRegisterSecurityKeyClicked();
|
||||
} else {
|
||||
this.props.onRegisterOneTimePasswordClicked();
|
||||
}
|
||||
return (
|
||||
<div className={classes.methodsContainer}>
|
||||
{methods}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderWithState(state: RemoteState) {
|
||||
|
@ -109,17 +120,6 @@ class SecondFactorView extends Component<Props, State> {
|
|||
<div className={classes.body}>
|
||||
{this.renderMode()}
|
||||
</div>
|
||||
<div className={classes.footer}>
|
||||
<a
|
||||
className={classes.otherMethod}
|
||||
href="#"
|
||||
onClick={this.toggleMode}>
|
||||
{this.state.mode === 'u2f' ? 'Use one-time password' : 'Use security key'}
|
||||
</a>
|
||||
<a className={classes.registerDevice} href="#" onClick={this.onRegisterClicked}>
|
||||
Register device
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
import React, { Component } from "react";
|
||||
|
||||
import securityKeyImage from '../../assets/images/security-key-hand.png';
|
||||
import { WithStyles, withStyles } from "@material-ui/core";
|
||||
import { WithStyles, withStyles, Button } from "@material-ui/core";
|
||||
|
||||
import styles from '../../assets/jss/views/SecurityKeyRegistrationView/SecurityKeyRegistrationView';
|
||||
import { RouteProps } from "react-router";
|
||||
import { RouteProps, RouterProps } from "react-router";
|
||||
import QueryString from 'query-string';
|
||||
import FormNotification from "../../components/FormNotification/FormNotification";
|
||||
import CircleLoader, { Status } from "../../components/CircleLoader/CircleLoader";
|
||||
|
||||
interface Props extends WithStyles, RouteProps {
|
||||
componentDidMount: (token: string) => void;
|
||||
export interface Props extends WithStyles, RouteProps, RouterProps {
|
||||
deviceRegistered: boolean | null;
|
||||
error: string | null;
|
||||
onInit: (token: string) => void;
|
||||
onBackClicked: () => void;
|
||||
}
|
||||
|
||||
class SecurityKeyRegistrationView extends Component<Props> {
|
||||
componentDidMount() {
|
||||
if (this.props.deviceRegistered) return;
|
||||
|
||||
if (!this.props.location) {
|
||||
console.error('There is no location to retrieve query params from...');
|
||||
return;
|
||||
|
@ -22,20 +28,53 @@ class SecurityKeyRegistrationView extends Component<Props> {
|
|||
console.error('Token parameter is expected and not provided');
|
||||
return;
|
||||
}
|
||||
this.props.componentDidMount(params['token'] as string);
|
||||
this.props.onInit(params['token'] as string);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classes} = this.props;
|
||||
private renderError() {
|
||||
const { classes } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.infoContainer}>Press the gold disk to register your security key</div>
|
||||
<div className={classes.imageContainer}>
|
||||
<img src={securityKeyImage} alt="security key" />
|
||||
<FormNotification show={true}>
|
||||
{this.props.error}
|
||||
</FormNotification>
|
||||
<div className={classes.retryButtonContainer}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={this.props.onBackClicked}>
|
||||
Back
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private renderRegistering() {
|
||||
const { classes } = this.props;
|
||||
let status = Status.LOADING;
|
||||
if (this.props.deviceRegistered === true) {
|
||||
status = Status.SUCCESSFUL;
|
||||
} else if (this.props.error) {
|
||||
status = Status.FAILURE;
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
<div className={classes.infoContainer}>Press the gold disk to register your security key</div>
|
||||
<div className={classes.imageContainer}>
|
||||
<CircleLoader status={status}></CircleLoader>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.props.error) {
|
||||
return this.renderError();
|
||||
}
|
||||
|
||||
return this.renderRegistering();
|
||||
}
|
||||
}
|
||||
|
||||
export default withStyles(styles)(SecurityKeyRegistrationView);
|
Loading…
Reference in New Issue
Block a user