diff --git a/docker-compose.yml b/docker-compose.yml index 08095730..1ea3c06b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -76,6 +76,7 @@ services: - ./docker/nginx/conf.d:/etc/nginx/conf.d - ./docker/nginx/conf.d.templates:/etc/nginx/templates - ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf + - ./docker/data/website/public/errors:/etc/nginx/errors networks: shared: ipv4_address: 10.10.10.30 @@ -99,7 +100,7 @@ services: logging: *default-logging volumes: - ./docker/data/website/.cache:/usr/app/.cache - - ./docker/data/website/.public:/usr/app/public + - ./docker/data/website/public:/usr/app/public env_file: - .env networks: diff --git a/docker/nginx/conf.d/include/location-skylink b/docker/nginx/conf.d/include/location-skylink index b214e3a9..25f59815 100644 --- a/docker/nginx/conf.d/include/location-skylink +++ b/docker/nginx/conf.d/include/location-skylink @@ -37,6 +37,13 @@ proxy_set_header User-Agent: Sia-Agent; proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args; +error_page 400 /etc/nginx/errors/400/index.html; +error_page 401 /etc/nginx/errors/401/index.html; +error_page 403 /etc/nginx/errors/403/index.html; +error_page 404 /etc/nginx/errors/404/index.html; +error_page 451 /etc/nginx/errors/451/index.html; +error_page 500 /etc/nginx/errors/500/index.html; + log_by_lua_block { local skynet_account = require("skynet.account") local skynet_modules = require("skynet.modules") diff --git a/packages/website/gatsby-browser.js b/packages/website/gatsby-browser.js index e086f2cb..423eca08 100644 --- a/packages/website/gatsby-browser.js +++ b/packages/website/gatsby-browser.js @@ -17,6 +17,7 @@ import * as React from "react"; import Layout from "./src/components/Layout"; export const wrapPageElement = ({ element, props }) => { + if (props.uri.startsWith("/errors")) return element; // props provide same data to Layout as Page element will get // including location, data, etc - you don't need to pass it return {element}; diff --git a/packages/website/src/components/ErrorPage.js b/packages/website/src/components/ErrorPage.js new file mode 100644 index 00000000..eb2202ff --- /dev/null +++ b/packages/website/src/components/ErrorPage.js @@ -0,0 +1,44 @@ +import * as React from "react"; +import { LogoBlackText } from "./Icons"; +import Seo from "./seo"; + +export default function ErrorPage({ statusCode, statusReason, header, subheader, redirect, more }) { + React.useEffect(() => { + if (redirect && typeof window !== "undefined") { + setTimeout(() => { + window.location.href = redirect; + }, 3000); // 3s + } + }, [redirect]); + + return ( + <> + + +
+
+
+ + +
+

{header}

+ +

{subheader}

+
+ + {more &&

{more}

} + + {redirect && ( +

+ If you're not redirected automatically,{" "} + + click here + +

+ )} +
+
+
+ + ); +} diff --git a/packages/website/src/pages/errors/400.js b/packages/website/src/pages/errors/400.js new file mode 100644 index 00000000..1921901b --- /dev/null +++ b/packages/website/src/pages/errors/400.js @@ -0,0 +1,21 @@ +import * as React from "react"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 400; +const statusReason = "Bad Request"; + +const header = "Bad Request"; +const subheader = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"; +const redirect = null; + +export default function BadRequest() { + return ( + + ); +} diff --git a/packages/website/src/pages/errors/401.js b/packages/website/src/pages/errors/401.js new file mode 100644 index 00000000..297f1706 --- /dev/null +++ b/packages/website/src/pages/errors/401.js @@ -0,0 +1,21 @@ +import * as React from "react"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 401; +const statusReason = "Unauthorized"; + +const header = "You must be authenticated to access this content"; +const subheader = "You're being redirected to the Log In page of this Skynet Portal"; +const redirect = `https://account.${process.env.PORTAL_DOMAIN}/auth/login`; + +export default function Unauthorized() { + return ( + + ); +} diff --git a/packages/website/src/pages/errors/403.js b/packages/website/src/pages/errors/403.js new file mode 100644 index 00000000..6a24a019 --- /dev/null +++ b/packages/website/src/pages/errors/403.js @@ -0,0 +1,21 @@ +import * as React from "react"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 403; +const statusReason = "Forbidden"; + +const header = "You are not authorized to access this content"; +const subheader = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"; +const redirect = null; + +export default function Forbidden() { + return ( + + ); +} diff --git a/packages/website/src/pages/errors/404.js b/packages/website/src/pages/errors/404.js new file mode 100644 index 00000000..7fc8026f --- /dev/null +++ b/packages/website/src/pages/errors/404.js @@ -0,0 +1,21 @@ +import * as React from "react"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 404; +const statusReason = "Not Found"; + +const header = "We could not load this content"; +const subheader = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"; +const redirect = null; + +export default function NotFound() { + return ( + + ); +} diff --git a/packages/website/src/pages/errors/451.js b/packages/website/src/pages/errors/451.js new file mode 100644 index 00000000..722a7833 --- /dev/null +++ b/packages/website/src/pages/errors/451.js @@ -0,0 +1,34 @@ +import * as React from "react"; +import Link from "../../components/Link"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 451; +const statusReason = "Unavailable For Legal Reasons"; + +const header = "This file is unavailable for legal reasons"; +const subheader = "This Skynet Portal has blocked access to this file, likely for legal reasons"; +const redirect = null; +const more = ( + <> + To learn more, see the{" "} + + Skynet FAQ + + +); + +export default function UnavailableForLegalReasons() { + return ( + + ); +} diff --git a/packages/website/src/pages/errors/500.js b/packages/website/src/pages/errors/500.js new file mode 100644 index 00000000..9b8800e8 --- /dev/null +++ b/packages/website/src/pages/errors/500.js @@ -0,0 +1,21 @@ +import * as React from "react"; +import ErrorPage from "../../components/ErrorPage"; + +const statusCode = 500; +const statusReason = "Internal Server Error"; + +const header = "Internal Server Error"; +const subheader = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor"; +const redirect = null; + +export default function InternalServerError() { + return ( + + ); +} diff --git a/packages/website/src/styles/global.css b/packages/website/src/styles/global.css index b7b62ed9..65fa8a04 100644 --- a/packages/website/src/styles/global.css +++ b/packages/website/src/styles/global.css @@ -2,6 +2,13 @@ @tailwind components; @tailwind utilities; +html, +body, +#___gatsby, +#gatsby-focus-wrapper { + @apply h-full; +} + .newsletter-message a { @apply text-primary; } diff --git a/packages/website/tailwind.config.js b/packages/website/tailwind.config.js index a9e9e91d..004baa78 100644 --- a/packages/website/tailwind.config.js +++ b/packages/website/tailwind.config.js @@ -58,15 +58,5 @@ module.exports = { }, }, }, - plugins: [ - require("@tailwindcss/typography"), - plugin(function ({ addBase, theme }) { - addBase({ - body: { - color: theme("textColor.palette.600"), - backgroundColor: theme("backgroundColor.palette.500"), - }, - }); - }), - ], + plugins: [require("@tailwindcss/typography")], };