From 3356b88a3e3254283fd3db982748f613fd43cadb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Mar 2022 11:23:55 +0100 Subject: [PATCH 1/7] feat(dashboard-v2): allow + + +

+ Don't have an account? Sign up +

+ + )} + +); + +LoginForm.propTypes = { + onSuccess: PropTypes.func.isRequired, +}; diff --git a/packages/dashboard-v2/src/components/forms/index.js b/packages/dashboard-v2/src/components/forms/index.js new file mode 100644 index 00000000..1cad6f41 --- /dev/null +++ b/packages/dashboard-v2/src/components/forms/index.js @@ -0,0 +1 @@ +export * from "./LoginForm"; diff --git a/packages/dashboard-v2/src/services/accountsService.js b/packages/dashboard-v2/src/services/accountsService.js new file mode 100644 index 00000000..37244e5f --- /dev/null +++ b/packages/dashboard-v2/src/services/accountsService.js @@ -0,0 +1,3 @@ +import ky from "ky"; + +export default ky.create({ prefixUrl: "/api" }); diff --git a/packages/dashboard-v2/yarn.lock b/packages/dashboard-v2/yarn.lock index 12ff2eb1..687e3c5b 100644 --- a/packages/dashboard-v2/yarn.lock +++ b/packages/dashboard-v2/yarn.lock @@ -3373,6 +3373,11 @@ dependencies: "@types/node" "*" +"@types/lodash@^4.14.175": + version "4.14.180" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.180.tgz#4ab7c9ddfc92ec4a887886483bc14c79fb380670" + integrity sha512-XOKXa1KIxtNXgASAnwj7cnttJxS4fksBRywK/9LzRV5YxrF80BXZIGeQSuoESQ/VkUj30Ae0+YcuHc15wJCB2g== + "@types/lodash@^4.14.92": version "4.14.178" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.178.tgz#341f6d2247db528d4a13ddbb374bcdc80406f4f8" @@ -6366,6 +6371,11 @@ deep-object-diff@^1.1.0: resolved "https://registry.yarnpkg.com/deep-object-diff/-/deep-object-diff-1.1.7.tgz#348b3246f426427dd633eaa50e1ed1fc2eafc7e4" integrity sha512-QkgBca0mL08P6HiOjoqvmm6xOAl2W6CT2+34Ljhg0OeFan8cwlcdq8jrLKsBBuUFAZLsN5b6y491KdKEoSo9lg== +deepmerge@^2.1.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" + integrity sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA== + deepmerge@^4.0.0, deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" @@ -7951,6 +7961,19 @@ format@^0.2.0: resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= +formik@^2.2.9: + version "2.2.9" + resolved "https://registry.yarnpkg.com/formik/-/formik-2.2.9.tgz#8594ba9c5e2e5cf1f42c5704128e119fc46232d0" + integrity sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA== + dependencies: + deepmerge "^2.1.1" + hoist-non-react-statics "^3.3.0" + lodash "^4.17.21" + lodash-es "^4.17.21" + react-fast-compare "^2.0.1" + tiny-warning "^1.0.2" + tslib "^1.10.0" + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" @@ -10357,6 +10380,11 @@ klona@^2.0.4: resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== +ky@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/ky/-/ky-0.30.0.tgz#a3d293e4f6c4604a9a4694eceb6ce30e73d27d64" + integrity sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog== + language-subtag-registry@~0.3.2: version "0.3.21" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" @@ -10510,6 +10538,11 @@ lock@^1.1.0: resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55" integrity sha1-UxV0mdFlOxNspmRRBx/KYVcD+lU= +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.clonedeep@4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" @@ -11183,6 +11216,11 @@ nano-css@^5.3.1: stacktrace-js "^2.0.2" stylis "^4.0.6" +nanoclone@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/nanoclone/-/nanoclone-0.2.1.tgz#dd4090f8f1a110d26bb32c49ed2f5b9235209ed4" + integrity sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA== + nanoid@^3.1.23, nanoid@^3.2.0, nanoid@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.1.tgz#6347a18cac88af88f58af0b3594b723d5e99bb35" @@ -12647,6 +12685,11 @@ proper-lockfile@^4.1.2: retry "^0.12.0" signal-exit "^3.0.2" +property-expr@^2.0.4: + version "2.0.5" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.5.tgz#278bdb15308ae16af3e3b9640024524f4dc02cb4" + integrity sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA== + property-information@^5.0.0, property-information@^5.3.0: version "5.6.0" resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" @@ -12942,6 +12985,11 @@ react-error-overlay@^6.0.9: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.10.tgz#0fe26db4fa85d9dbb8624729580e90e7159a59a6" integrity sha512-mKR90fX7Pm5seCOfz8q9F+66VCc1PGsWSBxKbITjfKVQHMNF2zudxHnMdJiB1fRCb+XsbQV9sO9DCkgsMQgBIA== +react-fast-compare@^2.0.1: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + react-fast-compare@^3.0.1, react-fast-compare@^3.1.1, react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" @@ -14830,6 +14878,11 @@ timsort@^0.3.0: resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= +tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + tinycolor2@^1.4.1: version "1.4.2" resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.2.tgz#3f6a4d1071ad07676d7fa472e1fac40a719d8803" @@ -14929,6 +14982,11 @@ token-types@^4.1.1: "@tokenizer/token" "^0.3.0" ieee754 "^1.2.1" +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -16036,6 +16094,19 @@ yoga-layout-prebuilt@^1.10.0: dependencies: "@types/yoga-layout" "1.9.2" +yup@^0.32.11: + version "0.32.11" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5" + integrity sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg== + dependencies: + "@babel/runtime" "^7.15.4" + "@types/lodash" "^4.14.175" + lodash "^4.17.21" + lodash-es "^4.17.21" + nanoclone "^0.2.1" + property-expr "^2.0.4" + toposort "^2.0.2" + yurnalist@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/yurnalist/-/yurnalist-2.1.0.tgz#44cf7ea5a33a8fab4968cc8c2970489f93760902" From dda507fd5fe963eb6a5f1f3295ecc58c1482d2fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Wed, 23 Mar 2022 11:44:00 +0100 Subject: [PATCH 6/7] feat(dashboard-v2): add /auth/login page --- .../src/components/NavBar/NavBar.js | 10 +++++--- packages/dashboard-v2/src/pages/auth/login.js | 23 +++++++++++++++++++ .../static/images/logo-black-text.svg | 19 +++++++++++++++ 3 files changed, 49 insertions(+), 3 deletions(-) create mode 100644 packages/dashboard-v2/src/pages/auth/login.js create mode 100644 packages/dashboard-v2/static/images/logo-black-text.svg diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 1db72dda..3d443627 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -1,4 +1,4 @@ -import { Link } from "gatsby"; +import { Link, navigate } from "gatsby"; import styled from "styled-components"; import { screen } from "../../lib/cssHelpers"; @@ -7,6 +7,7 @@ import { CogIcon, LockClosedIcon, SkynetLogoIcon } from "../Icons"; import { PageContainer } from "../PageContainer"; import { NavBarLink, NavBarSection } from "."; +import accountsService from "../../services/accountsService"; const NavBarContainer = styled.div.attrs({ className: `grid sticky top-0 bg-white z-10 shadow-sm`, @@ -77,9 +78,12 @@ export const NavBar = () => ( partiallyActive /> { + await accountsService.post("logout"); + navigate("/auth/login"); + }} activeClassName="text-primary" + className="cursor-pointer" icon={LockClosedIcon} label="Log out" /> diff --git a/packages/dashboard-v2/src/pages/auth/login.js b/packages/dashboard-v2/src/pages/auth/login.js new file mode 100644 index 00000000..077dda61 --- /dev/null +++ b/packages/dashboard-v2/src/pages/auth/login.js @@ -0,0 +1,23 @@ +import { navigate } from "gatsby"; + +import AuthLayout from "../../layouts/AuthLayout"; + +import { LoginForm } from "../../components/forms"; + +const LoginPage = ({ location }) => { + const query = new URLSearchParams(location.search); + const redirectTo = query.get("return_to"); + + return ( +
+
+ Skynet +
+ navigate(redirectTo || "/")} /> +
+ ); +}; + +LoginPage.Layout = AuthLayout; + +export default LoginPage; diff --git a/packages/dashboard-v2/static/images/logo-black-text.svg b/packages/dashboard-v2/static/images/logo-black-text.svg new file mode 100644 index 00000000..40e45ba8 --- /dev/null +++ b/packages/dashboard-v2/static/images/logo-black-text.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + From 731b1b6d52c515864bc054ff1e1ec63974c7f8d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Leszczyk?= Date: Thu, 24 Mar 2022 15:47:35 +0100 Subject: [PATCH 7/7] fix(dashboard-v2): address review comments --- packages/dashboard-v2/README.md | 4 +- packages/dashboard-v2/package.json | 2 +- .../src/components/NavBar/NavBar.js | 1 + .../src/components/forms/LoginForm.js | 127 +++++++++--------- 4 files changed, 71 insertions(+), 63 deletions(-) diff --git a/packages/dashboard-v2/README.md b/packages/dashboard-v2/README.md index c450ce50..ab0421f8 100644 --- a/packages/dashboard-v2/README.md +++ b/packages/dashboard-v2/README.md @@ -11,7 +11,7 @@ This is a Gatsby application. To run it locally, all you need is: ## Accessing remote APIs -To be able to log in on a local environment with your production credentials, you'll need to make the browser believe you're actually on the same domain, otherwise browser will block the session cookie. +To be able to log in on a local environment with your production credentials, you'll need to make the browser believe you're actually on the same domain, otherwise the browser will block the session cookie. To do the trick, edit your `/etc/hosts` file and add a record like this: @@ -19,7 +19,7 @@ To do the trick, edit your `/etc/hosts` file and add a record like this: 127.0.0.1 local.skynetpro.net ``` -then run `yarn secure` -- it will run `gatsby develop` with `--https --host=local.skynetpro.net -p=443` options. +then run `yarn develop:secure` -- it will run `gatsby develop` with `--https --host=local.skynetpro.net -p=443` options. If you're on macOS, you may need to `sudo` the command to successfully bind to port `443`. > **NOTE:** This should become easier once we have a docker image for the new dashboard. diff --git a/packages/dashboard-v2/package.json b/packages/dashboard-v2/package.json index b5f638d6..44f7595d 100644 --- a/packages/dashboard-v2/package.json +++ b/packages/dashboard-v2/package.json @@ -9,8 +9,8 @@ ], "scripts": { "develop": "gatsby develop", + "develop:secure": "gatsby develop --https --host=local.skynetpro.net -p=443", "start": "gatsby develop", - "secure": "gatsby develop --https --host=local.skynetpro.net -p=443", "build": "gatsby build", "serve": "gatsby serve", "clean": "gatsby clean", diff --git a/packages/dashboard-v2/src/components/NavBar/NavBar.js b/packages/dashboard-v2/src/components/NavBar/NavBar.js index 3d443627..65d9afe5 100644 --- a/packages/dashboard-v2/src/components/NavBar/NavBar.js +++ b/packages/dashboard-v2/src/components/NavBar/NavBar.js @@ -81,6 +81,7 @@ export const NavBar = () => ( onClick={async () => { await accountsService.post("logout"); navigate("/auth/login"); + // TODO: handle errors }} activeClassName="text-primary" className="cursor-pointer" diff --git a/packages/dashboard-v2/src/components/forms/LoginForm.js b/packages/dashboard-v2/src/components/forms/LoginForm.js index 93d7a1b9..61973215 100644 --- a/packages/dashboard-v2/src/components/forms/LoginForm.js +++ b/packages/dashboard-v2/src/components/forms/LoginForm.js @@ -1,3 +1,4 @@ +import { useState } from "react"; import PropTypes from "prop-types"; import { Formik, Form } from "formik"; import { Link } from "gatsby"; @@ -16,72 +17,78 @@ const loginSchema = Yup.object().shape({ const INVALID_CREDENTIALS_ERRORS = ["password mismatch", "user not found"]; -export const LoginForm = ({ onSuccess }) => ( - { - try { - await accountsService.post("login", { - json: values, - }); +export const LoginForm = ({ onSuccess }) => { + const [error, setError] = useState(null); - onSuccess(); - } catch (err) { - if (err.response) { - const data = await err.response.json(); + return ( + { + try { + await accountsService.post("login", { + json: values, + }); - if (INVALID_CREDENTIALS_ERRORS.includes(data.message)) { - setErrors({ - email: "Invalid e-mail address or password", - password: "Invalid e-mail address or password", - }); + onSuccess(); + } catch (err) { + if (err.response) { + const data = await err.response.json(); + + if (INVALID_CREDENTIALS_ERRORS.includes(data.message)) { + setError("Invalid email address or password."); + } else { + setError(data.message); + } + } else { + setError("An error occured when logging you in. Please try again."); } } - } - }} - > - {({ errors, touched }) => ( -
-

Log in to your account

- - -
- - Forgot your password? - -
+ }} + > + {({ errors, touched }) => ( + +

Log in to your account

+ {error &&

{error}

} + + +
+ + Forgot your password? + +
-
- -
+
+ +
-

- Don't have an account? Sign up -

- - )} -
-); +

+ Don't have an account? Sign up +

+ + )} +
+ ); +}; LoginForm.propTypes = { onSuccess: PropTypes.func.isRequired,