Compare commits

...
This repository has been archived on 2022-10-07. You can view files and clone it, but cannot push or open issues or pull requests.

17 Commits

Author SHA1 Message Date
Karol Wypchlo ab317b428a
add return to 2022-05-20 15:04:13 +02:00
Karol Wypchlo d6bfb50516
increate timeout to 5s 2022-05-20 15:01:38 +02:00
Karol Wypchlo dc602054f2
try internal location 2022-05-20 14:59:19 +02:00
Karol Wypchlo 3fe46e3ef6
update alias 2022-05-20 14:50:04 +02:00
Karol Wypchlo b838979b94
update root 2022-05-20 14:46:42 +02:00
Karol Wypchlo 18fddcd8a4
update root 2022-05-20 14:19:05 +02:00
Karol Wypchlo f5d7973eab
fix path 2022-05-20 13:01:10 +02:00
Karol Wypchlo 83521f141f
test without website 2022-05-20 12:53:31 +02:00
Karol Wypchlo 7c52fe77e1
try error pages outside location 2022-05-20 12:48:51 +02:00
Karol Wypchlo 35bf172d28
use static html error page 2022-05-20 12:37:41 +02:00
Karol Wypchlo 185daf6a08
allow lua to use error pages 2022-05-19 15:49:48 +02:00
Karol Wypchlo 2f60d02131
proxy_intercept_errors 2022-05-19 15:35:58 +02:00
Karol Wypchlo 9d8b34af43
Merge remote-tracking branch 'origin/master' into error-pages 2022-05-19 15:21:45 +02:00
Karol Wypchlo 5ac6d34e00
Revert "Revert "fix""
This reverts commit d858b8b33e.
2022-05-16 16:43:24 +02:00
Karol Wypchlo d858b8b33e
Revert "fix"
This reverts commit 1678b17e9a.
2022-05-16 16:37:47 +02:00
Karol Wypchlo 1678b17e9a
fix 2022-05-16 16:35:47 +02:00
Karol Wypchlo 69c6f9e42a
error pages 2022-05-16 12:59:11 +02:00
22 changed files with 316 additions and 37 deletions

View File

@ -74,7 +74,7 @@ services:
- ./docker/data/certbot:/etc/letsencrypt - ./docker/data/certbot:/etc/letsencrypt
- ./docker/nginx/libs:/etc/nginx/libs - ./docker/nginx/libs:/etc/nginx/libs
- ./docker/nginx/conf.d:/etc/nginx/conf.d - ./docker/nginx/conf.d:/etc/nginx/conf.d
- ./docker/nginx/conf.d.templates:/etc/nginx/templates - ./docker/nginx/templates:/etc/nginx/templates
- ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf - ./docker/nginx/nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf
networks: networks:
shared: shared:
@ -99,7 +99,7 @@ services:
logging: *default-logging logging: *default-logging
volumes: volumes:
- ./docker/data/website/.cache:/usr/app/.cache - ./docker/data/website/.cache:/usr/app/.cache
- ./docker/data/website/.public:/usr/app/public - ./docker/data/website/public:/usr/app/public
env_file: env_file:
- .env - .env
networks: networks:

View File

@ -15,10 +15,10 @@ rewrite_by_lua_block {
-- print error and exit with 500 or exit with response if status is not 200 -- print error and exit with 500 or exit with response if status is not 200
if hnsres_err or (hnsres_res and hnsres_res.status ~= ngx.HTTP_OK) then if hnsres_err or (hnsres_res and hnsres_res.status ~= ngx.HTTP_OK) then
ngx.status = (hnsres_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or hnsres_res.status -- ngx.status = (hnsres_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or hnsres_res.status
ngx.header["content-type"] = "text/plain" -- ngx.header["content-type"] = "text/plain"
ngx.say(hnsres_err or hnsres_res.body) -- ngx.say(hnsres_err or hnsres_res.body)
return ngx.exit(ngx.status) return ngx.exit((hnsres_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or hnsres_res.status)
end end
-- since /hnsres endpoint response is a json, we need to decode it before we access it -- since /hnsres endpoint response is a json, we need to decode it before we access it
@ -48,10 +48,10 @@ rewrite_by_lua_block {
-- print error and exit with 500 or exit with response if status is not 200 -- print error and exit with 500 or exit with response if status is not 200
if registry_err or (registry_res and registry_res.status ~= ngx.HTTP_OK) then if registry_err or (registry_res and registry_res.status ~= ngx.HTTP_OK) then
ngx.status = (registry_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or registry_res.status -- ngx.status = (registry_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or registry_res.status
ngx.header["content-type"] = "text/plain" -- ngx.header["content-type"] = "text/plain"
ngx.say(registry_err or registry_res.body) -- ngx.say(registry_err or registry_res.body)
return ngx.exit(ngx.status) return ngx.exit((registry_err and ngx.HTTP_INTERNAL_SERVER_ERROR) or registry_res.status)
end end
-- since /skynet/registry endpoint response is a json, we need to decode it before we access it -- since /skynet/registry endpoint response is a json, we need to decode it before we access it

View File

@ -36,6 +36,7 @@ proxy_read_timeout 600;
proxy_set_header User-Agent: Sia-Agent; proxy_set_header User-Agent: Sia-Agent;
proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args; proxy_pass http://sia:9980/skynet/skylink/$skylink$path$is_args$args;
proxy_intercept_errors on;
log_by_lua_block { log_by_lua_block {
local skynet_account = require("skynet.account") local skynet_account = require("skynet.account")

View File

@ -23,12 +23,19 @@ rewrite ^/stats /skynet/stats permanent;
rewrite ^/skynet/blacklist /skynet/blocklist permanent; rewrite ^/skynet/blacklist /skynet/blocklist permanent;
rewrite ^/docs(?:/(.*))?$ https://sdk.skynetlabs.com/$1 permanent; rewrite ^/docs(?:/(.*))?$ https://sdk.skynetlabs.com/$1 permanent;
location / { error_page 401 /401.html;
include /etc/nginx/conf.d/include/cors; location = /401.html {
root /etc/nginx/conf.d/pages;
proxy_pass http://website:9000; allow all;
internal;
} }
#location / {
# include /etc/nginx/conf.d/include/cors;
#
# proxy_pass http://website:9000;
#}
location /skynet/blocklist { location /skynet/blocklist {
include /etc/nginx/conf.d/include/cors; include /etc/nginx/conf.d/include/cors;

View File

@ -23,10 +23,10 @@ location / {
ngx.var.skylink = match_skylink[1] ngx.var.skylink = match_skylink[1]
ngx.var.path = match_skylink[2] or "/" ngx.var.path = match_skylink[2] or "/"
else else
ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status -- ngx.status = (err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status
ngx.header["content-type"] = "text/plain" -- ngx.header["content-type"] = "text/plain"
ngx.say(err or res.body) -- ngx.say(err or res.body)
ngx.exit(ngx.status) ngx.exit((err and ngx.HTTP_INTERNAL_SERVER_ERROR) or res.status)
end end
else else
local resolved = cjson.decode(res.body) local resolved = cjson.decode(res.body)

View File

@ -44,18 +44,18 @@ end
-- handle request exit when access to portal should be restricted to authenticated users only -- handle request exit when access to portal should be restricted to authenticated users only
function _M.exit_access_unauthorized(message) function _M.exit_access_unauthorized(message)
ngx.status = ngx.HTTP_UNAUTHORIZED -- ngx.status = ngx.HTTP_UNAUTHORIZED
ngx.header["content-type"] = "text/plain" -- ngx.header["content-type"] = "text/plain"
ngx.say(message or "Portal operator restricted access to authenticated users only") -- ngx.say(message or "Portal operator restricted access to authenticated users only")
return ngx.exit(ngx.status) return ngx.exit(ngx.HTTP_UNAUTHORIZED)
end end
-- handle request exit when access to portal should be restricted to subscription users only -- handle request exit when access to portal should be restricted to subscription users only
function _M.exit_access_forbidden(message) function _M.exit_access_forbidden(message)
ngx.status = ngx.HTTP_FORBIDDEN -- ngx.status = ngx.HTTP_FORBIDDEN
ngx.header["content-type"] = "text/plain" -- ngx.header["content-type"] = "text/plain"
ngx.say(message or "Portal operator restricted access to users with active subscription only") -- ngx.say(message or "Portal operator restricted access to users with active subscription only")
return ngx.exit(ngx.status) return ngx.exit(ngx.HTTP_FORBIDDEN)
end end
function _M.accounts_enabled() function _M.accounts_enabled()

View File

@ -0,0 +1,90 @@
<!DOCTYPE html>
<html class="h-full">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- meta tags generated with https://metatags.io/ -->
<title>401: Unauthorized</title>
<meta name="title" content="401: Unauthorized" />
<meta
name="description"
content="You must be authenticated to access this content"
/>
<!-- svg favicon encoded with https://yoksel.github.io/url-encoder/ -->
<link
rel="icon"
href="data:image/svg+xml, %3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg' fill='%2300C65E' %3E%3Ctitle%3ESkynet%3C/title%3E%3Cpath d='m-.0004 6.4602 21.3893 11.297c.561.2935.6633 1.0532.1999 1.4846h-.011a10.0399 10.0399 0 0 1-2.2335 1.5307c-6.912 3.4734-14.9917-1.838-14.5438-9.5605l2.8601 1.9752c.856 4.508 5.6187 7.1094 9.8742 5.3932zm8.6477 3.1509 14.3661 5.6785a.8704.8704 0 0 1 .5197 1.0466v.0182c-.1537.5377-.7668.7938-1.2575.5252zm5.2896-7.4375c2.7093-.2325 6.0946.7869 8.1116 3.3871 1.699 2.1951 2.0497 4.8772 1.9298 7.6465v-.007c-.0478.5874-.6494.9616-1.1975.745l-9.7652-3.8596 9.0656 2.4313a7.296 7.296 0 0 0-1.0677-4.5631c-2.9683-4.7678-9.9847-4.5344-12.6297.4201a7.5048 7.5048 0 0 0-.398.8831L5.5546 7.9614c.069-.1017.1417-.198.2144-.2962.1163-.2416.2417-.487.3798-.7268 1.6118-2.7911 4.3102-4.4338 7.1558-4.6973.2108-.0182.4215-.049.6323-.0672z' /%3E%3C/svg%3E"
type="image/svg+xml"
/>
<!-- https://fonts.google.com/specimen/Sora -->
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Sora:wght@400;800&display=swap"
rel="stylesheet"
/>
<!-- https://tailwindcss.com/docs/installation/play-cdn -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: { extend: { fontFamily: { sans: ["Sora", "sans-serif"] } } },
};
</script>
</head>
<body class="h-full">
<div
class="bg-white min-h-full px-4 py-16 sm:px-6 sm:py-24 md:grid md:place-items-center lg:px-8"
>
<div class="max-w-max mx-auto">
<main class="sm:flex">
<svg
role="img"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
height="88"
fill="#00C65E"
>
<title>Skynet</title>
<path
d="m-.0004 6.4602 21.3893 11.297c.561.2935.6633 1.0532.1999 1.4846h-.011a10.0399 10.0399 0 0 1-2.2335 1.5307c-6.912 3.4734-14.9917-1.838-14.5438-9.5605l2.8601 1.9752c.856 4.508 5.6187 7.1094 9.8742 5.3932zm8.6477 3.1509 14.3661 5.6785a.8704.8704 0 0 1 .5197 1.0466v.0182c-.1537.5377-.7668.7938-1.2575.5252zm5.2896-7.4375c2.7093-.2325 6.0946.7869 8.1116 3.3871 1.699 2.1951 2.0497 4.8772 1.9298 7.6465v-.007c-.0478.5874-.6494.9616-1.1975.745l-9.7652-3.8596 9.0656 2.4313a7.296 7.296 0 0 0-1.0677-4.5631c-2.9683-4.7678-9.9847-4.5344-12.6297.4201a7.5048 7.5048 0 0 0-.398.8831L5.5546 7.9614c.069-.1017.1417-.198.2144-.2962.1163-.2416.2417-.487.3798-.7268 1.6118-2.7911 4.3102-4.4338 7.1558-4.6973.2108-.0182.4215-.049.6323-.0672z"
/>
</svg>
<div class="sm:ml-6">
<div class="sm:border-l sm:border-gray-200 sm:pl-6">
<h1
class="text-xl font-extrabold text-gray-900 tracking-tight sm:text-2xl"
>
You must be authenticated to access this content
</h1>
<p class="mt-1 text-base text-gray-500">
You're being redirected to the Log In page of this Skynet Portal
</p>
<p class="mt-2 text-sm text-gray-300">HTTP 401: Unauthorized</p>
</div>
<div
class="mt-10 flex space-x-3 sm:border-l sm:border-transparent sm:pl-6"
>
<p class="mt-1 text-sm text-gray-500">
If you're not redirected automatically,
<a
href="https://account.${PORTAL_DOMAIN}/auth/login"
class="text-[#00C65E]"
>click here</a
>.
</p>
</div>
</div>
</main>
</div>
</div>
<script>
// prevent auto redirect if not on portal domain to allow local development
if (window.location.hostname.endsWith("${PORTAL_DOMAIN}")) {
setTimeout(function redirect() {
const encodedReturnTo = encodeURIComponent(window.location.href);
window.location.href = `https://account.${PORTAL_DOMAIN}/auth/login?return_to=${encodedReturnTo}`;
}, 5000); // redirect after 5 secons
}
</script>
</body>
</html>

View File

@ -17,6 +17,7 @@ import * as React from "react";
import Layout from "./src/components/Layout"; import Layout from "./src/components/Layout";
export const wrapPageElement = ({ element, props }) => { export const wrapPageElement = ({ element, props }) => {
if (props.uri.startsWith("/errors")) return element;
// props provide same data to Layout as Page element will get // props provide same data to Layout as Page element will get
// including location, data, etc - you don't need to pass it // including location, data, etc - you don't need to pass it
return <Layout {...props}>{element}</Layout>; return <Layout {...props}>{element}</Layout>;

View File

@ -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 (
<>
<Seo title={`${statusCode}: ${statusReason}`} />
<div className="bg-white min-h-full px-4 py-16 sm:px-6 sm:py-24 md:grid md:place-items-center lg:px-8">
<div className="max-w-max mx-auto">
<main className="sm:flex-col sm:max-w-3xl space-y-4 sm:space-y-6">
<LogoBlackText className="h-10 ml-[-10px]" />
<div className="flex-col space-y-1 sm:space-y-2">
<h1 className="text-lg sm:text-2xl">{header}</h1>
<p className="text-sm sm:text-md text-palette-400">{subheader}</p>
</div>
{more && <p className="text-sm text-palette-300">{more}</p>}
{redirect && (
<p className="text-xs text-palette-300">
If you're not redirected automatically,{" "}
<a href={redirect} className="text-primary hover:text-primary-light transition-colors duration-200">
click here
</a>
</p>
)}
</main>
</div>
</div>
</>
);
}

View File

@ -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 (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
redirect={redirect}
/>
);
}

View File

@ -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 (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
redirect={redirect}
/>
);
}

View File

@ -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 (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
redirect={redirect}
/>
);
}

View File

@ -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 (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
redirect={redirect}
/>
);
}

View File

@ -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{" "}
<Link
href="https://support.skynetlabs.com/key-concepts/faqs#is-skynet-censorship-free"
className="text-primary hover:text-primary-light transition-colors duration-200"
>
Skynet FAQ
</Link>
</>
);
export default function UnavailableForLegalReasons() {
return (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
more={more}
redirect={redirect}
/>
);
}

View File

@ -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 (
<ErrorPage
statusCode={statusCode}
statusReason={statusReason}
header={header}
subheader={subheader}
redirect={redirect}
/>
);
}

View File

@ -2,6 +2,13 @@
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
html,
body,
#___gatsby,
#gatsby-focus-wrapper {
@apply h-full;
}
.newsletter-message a { .newsletter-message a {
@apply text-primary; @apply text-primary;
} }

View File

@ -58,15 +58,5 @@ module.exports = {
}, },
}, },
}, },
plugins: [ plugins: [require("@tailwindcss/typography")],
require("@tailwindcss/typography"),
plugin(function ({ addBase, theme }) {
addBase({
body: {
color: theme("textColor.palette.600"),
backgroundColor: theme("backgroundColor.palette.500"),
},
});
}),
],
}; };