From 924815e62923ced83fb62b2129fc351292d1dfff Mon Sep 17 00:00:00 2001 From: Grant Date: Fri, 5 Jul 2024 23:06:26 -0600 Subject: [PATCH] rapid patch: add event info banner (related #69) --- Dockerfile | 1 + .../src/components/EventInfoOverlay.tsx | 84 +++++++++++++++++++ .../client/src/components/Header/Header.tsx | 2 + .../src/components/Info/InfoSidebar.tsx | 13 ++- .../client/src/components/Toolbar/Palette.tsx | 14 +++- packages/client/src/index.html | 5 +- packages/client/src/vite-env.d.ts | 3 +- packages/server/src/api/client.ts | 16 ++++ packages/server/src/index.ts | 32 +++---- packages/server/src/lib/oidc.ts | 7 ++ 10 files changed, 154 insertions(+), 23 deletions(-) create mode 100644 packages/client/src/components/EventInfoOverlay.tsx diff --git a/Dockerfile b/Dockerfile index 490df03..c455fa9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -51,6 +51,7 @@ RUN sed -i -e 's/"main": ".*"/"main": ".\/dist\/index.js"/' packages/lib/package # --- build main client --- +ARG VITE_INCLUDE_EVENT_INFO RUN npm -w packages/client run build # --- build admin --- diff --git a/packages/client/src/components/EventInfoOverlay.tsx b/packages/client/src/components/EventInfoOverlay.tsx new file mode 100644 index 0000000..6ca75ee --- /dev/null +++ b/packages/client/src/components/EventInfoOverlay.tsx @@ -0,0 +1,84 @@ +import React, { useEffect, useRef } from "react"; +import { useAppContext } from "../contexts/AppContext"; +import { Button } from "@nextui-org/react"; + +const EVENT_START = 1720756800000; // midnight 7/12/2024 eastern + +/** + * *oh god the terrible code* + * + * not sure of another clean way to do this + * + * This is used to show details about the event, immediately on page load + * + * used by the canvas preview page to get people hyped up for the event (<7 days before) + */ +export const EventInfoOverlay = ({ children }: React.PropsWithChildren) => { + const { setInfoSidebar, setSettingsSidebar } = useAppContext(); + const $countdown = useRef(null); + + const getCountdown = () => { + // date math always confuses me... + // https://stackoverflow.com/a/7709819 + + const now = Date.now(); + const ms = EVENT_START - now; + const days = Math.floor(ms / (1000 * 60 * 60 * 24)); + const hours = Math.floor((ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor( + ((ms % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) / (1000 * 60) + ); + const seconds = Math.round( + (((ms % (1000 * 60 * 60 * 24)) % (1000 * 60 * 60)) % (1000 * 60)) / 1000 + ); + + return [days, hours, minutes, seconds]; + }; + + const updateTime = () => { + if (!$countdown.current) return; + + const [days, hours, minutes, seconds] = getCountdown(); + + $countdown.current.innerText = [ + days && days + "d", + hours && hours + "h", + minutes && minutes + "m", + seconds && seconds + "s", + ] + .filter((a) => a) + .join(" "); + + $countdown.current.title = `${days} days ${hours} hours ${minutes} minutes ${seconds} seconds`; + }; + + useEffect(() => { + var interval = setInterval(updateTime, 1000); + updateTime(); + + return () => { + clearInterval(interval); + }; + }, []); + + return ( +
+
+

Canvas 2024

+

($countdown.current = r)} className="text-3xl">

+
+ +
+ +
+ + +
+
+ ); +}; diff --git a/packages/client/src/components/Header/Header.tsx b/packages/client/src/components/Header/Header.tsx index 6959189..049cb01 100644 --- a/packages/client/src/components/Header/Header.tsx +++ b/packages/client/src/components/Header/Header.tsx @@ -4,6 +4,7 @@ import { User } from "./User"; import { Debug } from "@sc07-canvas/lib/src/debug"; import React, { lazy } from "react"; import { AccountStanding } from "./AccountStanding"; +import { EventInfoOverlay } from "../EventInfoOverlay"; const OpenChatButton = lazy(() => import("../Chat/OpenChatButton")); @@ -18,6 +19,7 @@ export const Header = () => { return (
+ {import.meta.env.VITE_INCLUDE_EVENT_INFO && }
{!connected && ( diff --git a/packages/client/src/components/Info/InfoSidebar.tsx b/packages/client/src/components/Info/InfoSidebar.tsx index bff1b52..078ef62 100644 --- a/packages/client/src/components/Info/InfoSidebar.tsx +++ b/packages/client/src/components/Info/InfoSidebar.tsx @@ -45,12 +45,23 @@ export const InfoSidebar = () => { Discord
- + + Build {__COMMIT_HASH__} ); diff --git a/packages/client/src/components/Toolbar/Palette.tsx b/packages/client/src/components/Toolbar/Palette.tsx index 751516a..c805784 100644 --- a/packages/client/src/components/Toolbar/Palette.tsx +++ b/packages/client/src/components/Toolbar/Palette.tsx @@ -67,10 +67,16 @@ export const Palette = () => { {!user && (
- You are not logged in - - Login - + {import.meta.env.VITE_INCLUDE_EVENT_INFO ? ( + <>The event hasn't started yet + ) : ( + <> + You are not logged in + + Login + + + )}
)} diff --git a/packages/client/src/index.html b/packages/client/src/index.html index 6b9c5e4..737189d 100644 --- a/packages/client/src/index.html +++ b/packages/client/src/index.html @@ -4,12 +4,15 @@ - canvas + Canvas + + +
diff --git a/packages/client/src/vite-env.d.ts b/packages/client/src/vite-env.d.ts index a8df2a6..ff03115 100644 --- a/packages/client/src/vite-env.d.ts +++ b/packages/client/src/vite-env.d.ts @@ -1,8 +1,7 @@ /// interface ImportMetaEnv { - readonly VITE_API_HOST: string; - readonly VITE_MATRIX_HOST: string; + readonly VITE_INCLUDE_EVENT_INFO: boolean; } interface ImportMeta { diff --git a/packages/server/src/api/client.ts b/packages/server/src/api/client.ts index 82010b3..4eb4aa6 100644 --- a/packages/server/src/api/client.ts +++ b/packages/server/src/api/client.ts @@ -31,6 +31,14 @@ const app = Router(); * Redirect to actual authorization page */ app.get("/login", (req, res) => { + if (process.env.INHIBIT_LOGINS) { + res.status(400).json({ + success: false, + error: "Login is not permitted.", + }); + return; + } + res.redirect( OpenID.client.authorizationUrl({ prompt: "consent", @@ -57,6 +65,14 @@ app.post("/logout", (req, res) => { * This executes multiple database queries and should be ratelimited */ app.get("/callback", RateLimiter.HIGH, async (req, res) => { + if (process.env.INHIBIT_LOGINS) { + res.status(400).json({ + success: false, + error: "Login is not permitted.", + }); + return; + } + let exchange: TokenSet; try { diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index d04a609..4848f73 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -58,24 +58,26 @@ if (!process.env.REDIS_RATELIMIT_PREFIX) { ); } -if (!process.env.AUTH_ENDPOINT) { - Logger.error("AUTH_ENDPOINT is not defined"); - process.exit(1); -} +if (!process.env.INHIBIT_LOGIN) { + if (!process.env.AUTH_ENDPOINT) { + Logger.error("AUTH_ENDPOINT is not defined"); + process.exit(1); + } -if (!process.env.AUTH_CLIENT) { - Logger.error("AUTH_CLIENT is not defined"); - process.exit(1); -} + if (!process.env.AUTH_CLIENT) { + Logger.error("AUTH_CLIENT is not defined"); + process.exit(1); + } -if (!process.env.AUTH_SECRET) { - Logger.error("AUTH_SECRET is not defined"); - process.exit(1); -} + if (!process.env.AUTH_SECRET) { + Logger.error("AUTH_SECRET is not defined"); + process.exit(1); + } -if (!process.env.OIDC_CALLBACK_HOST) { - Logger.error("OIDC_CALLBACK_HOST is not defined"); - process.exit(1); + if (!process.env.OIDC_CALLBACK_HOST) { + Logger.error("OIDC_CALLBACK_HOST is not defined"); + process.exit(1); + } } // run startup tasks, all of these need to be completed to serve diff --git a/packages/server/src/lib/oidc.ts b/packages/server/src/lib/oidc.ts index cf184ae..92447d0 100644 --- a/packages/server/src/lib/oidc.ts +++ b/packages/server/src/lib/oidc.ts @@ -5,6 +5,13 @@ class OpenID_ { client: BaseClient = {} as any; async setup() { + if (process.env.INHIBIT_LOGIN) { + console.warn( + "OpenID is not setup; INHIBIT_LOGIN environment variable set! Proceed with caution!" + ); + return; + } + const { AUTH_ENDPOINT, AUTH_CLIENT, AUTH_SECRET } = process.env; this.issuer = await Issuer.discover(AUTH_ENDPOINT);