diff --git a/docker-compose.accounts.yml b/docker-compose.accounts.yml index 73953a57..5d67a294 100644 --- a/docker-compose.accounts.yml +++ b/docker-compose.accounts.yml @@ -21,8 +21,8 @@ services: accounts: # uncomment "build" and comment out "image" to build from sources - # build: https://github.com/SkynetLabs/skynet-accounts.git#main - image: skynetlabs/skynet-accounts + build: https://github.com/SkynetLabs/skynet-accounts.git#main + # image: skynetlabs/skynet-accounts container_name: accounts restart: unless-stopped logging: *default-logging diff --git a/docker/nginx/conf.d/server/server.account b/docker/nginx/conf.d/server/server.account index 127ba4bf..fcdcd3b5 100644 --- a/docker/nginx/conf.d/server/server.account +++ b/docker/nginx/conf.d/server/server.account @@ -4,7 +4,7 @@ include /etc/nginx/conf.d/include/ssl-settings; include /etc/nginx/conf.d/include/init-optional-variables; location / { - proxy_pass http://dashboard:3000; + proxy_pass http://dashboard-v2:9000; } location /health { diff --git a/packages/dashboard-v2/src/contexts/user/UserProvider.js b/packages/dashboard-v2/src/contexts/user/UserProvider.js index bb10ffe4..c46257e0 100644 --- a/packages/dashboard-v2/src/contexts/user/UserProvider.js +++ b/packages/dashboard-v2/src/contexts/user/UserProvider.js @@ -1,17 +1,29 @@ +import { navigate } from "gatsby"; import { useEffect, useState } from "react"; import useSWRImmutable from "swr/immutable"; +import { UnauthorizedError } from "../../lib/swrConfig"; import { UserContext } from "./UserContext"; -export const UserProvider = ({ children }) => { +export const UserProvider = ({ children, allowGuests = false, allowAuthenticated = true }) => { const { data: user, error, mutate } = useSWRImmutable("user"); const [loading, setLoading] = useState(true); useEffect(() => { - if (user || error) { - setLoading(false); + if (user) { + if (!allowAuthenticated) { + navigate("/"); + } else { + setLoading(false); + } + } else if (error) { + if (error instanceof UnauthorizedError && !allowGuests) { + navigate(`/auth/login?return_to=${encodeURIComponent(window.location.href)}`); + } else { + setLoading(false); + } } - }, [user, error]); + }, [user, error, allowGuests, allowAuthenticated]); return {children}; }; diff --git a/packages/dashboard-v2/src/layouts/AuthLayout.js b/packages/dashboard-v2/src/layouts/AuthLayout.js index 85604321..281e3b1e 100644 --- a/packages/dashboard-v2/src/layouts/AuthLayout.js +++ b/packages/dashboard-v2/src/layouts/AuthLayout.js @@ -3,7 +3,7 @@ import styled from "styled-components"; import { SWRConfig } from "swr"; import { UserProvider } from "../contexts/user"; -import { guestsOnly, allUsers } from "../lib/swrConfig"; +import { allUsers } from "../lib/swrConfig"; const Layout = styled.div.attrs({ className: "min-h-screen w-screen bg-black flex", @@ -22,12 +22,12 @@ const Content = styled.div.attrs({ })``; const AuthLayout = - (swrConfig) => + (userProviderProps) => ({ children }) => { return ( <> - - + +
@@ -45,6 +45,12 @@ const AuthLayout = }; // Some pages (e.g. email confirmation) need to be accessible to both logged-in and guest users. -export const AllUsersAuthLayout = AuthLayout(allUsers); +export const AllUsersAuthLayout = AuthLayout({ + allowGuests: true, + allowAuthenticated: true, +}); -export default AuthLayout(guestsOnly); +export default AuthLayout({ + allowGuests: true, + allowAuthenticated: false, +}); diff --git a/packages/dashboard-v2/src/layouts/DashboardLayout.js b/packages/dashboard-v2/src/layouts/DashboardLayout.js index fe4c5385..35bcb3ab 100644 --- a/packages/dashboard-v2/src/layouts/DashboardLayout.js +++ b/packages/dashboard-v2/src/layouts/DashboardLayout.js @@ -2,7 +2,7 @@ import * as React from "react"; import styled from "styled-components"; import { SWRConfig } from "swr"; -import { authenticatedOnly } from "../lib/swrConfig"; +import { allUsers } from "../lib/swrConfig"; import { PageContainer } from "../components/PageContainer"; import { NavBar } from "../components/NavBar"; @@ -33,8 +33,8 @@ const Layout = ({ children }) => { const DashboardLayout = ({ children }) => { return ( <> - - + + diff --git a/packages/dashboard-v2/src/layouts/UserSettingsLayout.js b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js index d7b9b7d4..2cf36e1d 100644 --- a/packages/dashboard-v2/src/layouts/UserSettingsLayout.js +++ b/packages/dashboard-v2/src/layouts/UserSettingsLayout.js @@ -3,7 +3,7 @@ import { Link } from "gatsby"; import styled from "styled-components"; import { SWRConfig } from "swr"; -import { authenticatedOnly } from "../lib/swrConfig"; +import { allUsers } from "../lib/swrConfig"; import { PageContainer } from "../components/PageContainer"; import { NavBar } from "../components/NavBar"; @@ -67,8 +67,8 @@ const Content = styled.main.attrs({ `; const UserSettingsLayout = ({ children }) => ( - - + + diff --git a/packages/dashboard-v2/src/lib/swrConfig.js b/packages/dashboard-v2/src/lib/swrConfig.js index 16e2dbfb..5ad10093 100644 --- a/packages/dashboard-v2/src/lib/swrConfig.js +++ b/packages/dashboard-v2/src/lib/swrConfig.js @@ -1,39 +1,19 @@ -import { navigate } from "gatsby"; import { StatusCodes } from "http-status-codes"; -// TODO: portal-aware URL -const baseUrl = process.env.NODE_ENV !== "production" ? "/api" : "https://account.skynetpro.net/api"; - -const redirectUnauthenticated = (key) => - fetch(`${baseUrl}/${key}`).then((response) => { - if (response.status === StatusCodes.UNAUTHORIZED) { - navigate(`/auth/login?return_to=${encodeURIComponent(window.location.href)}`); - return null; - } - - return response.json(); - }); - -const redirectAuthenticated = (key) => - fetch(`${baseUrl}/${key}`).then(async (response) => { - if (response.ok) { - await navigate("/"); - return response.json(); - } - - // If there was an error, let's throw so useSWR's "error" property is populated instead "data". - const data = await response.json(); - throw new Error(data?.message || `Error occured when trying to fetch: ${key}`); - }); +export class UnauthorizedError extends Error {} export const allUsers = { - fetcher: (key) => fetch(`${baseUrl}/${key}`).then((response) => response.json()), -}; + fetcher: (key) => fetch(`/api/${key}`).then(async (response) => { + if (response.ok) { + return response.json(); + } + + const data = await response.json(); -export const authenticatedOnly = { - fetcher: redirectUnauthenticated, -}; - -export const guestsOnly = { - fetcher: redirectAuthenticated, + if (response.status === StatusCodes.UNAUTHORIZED) { + throw new UnauthorizedError(data?.message || "Unauthorized"); + } + + throw new Error(data?.message || `Error occurred when trying to fetch: ${key}`); + }) }; diff --git a/packages/dashboard-v2/src/services/skynetClient.js b/packages/dashboard-v2/src/services/skynetClient.js index 0549085c..a01e96f9 100644 --- a/packages/dashboard-v2/src/services/skynetClient.js +++ b/packages/dashboard-v2/src/services/skynetClient.js @@ -1,3 +1,3 @@ import { SkynetClient } from "skynet-js"; -export default new SkynetClient("https://skynetpro.net"); // TODO: proper API url +export default new SkynetClient(`https://${process.env.GATSBY_PORTAL_DOMAIN}`);