[FEATURE] Initial Cairo Auth Integration

This commit is contained in:
Dunemask 2024-02-04 01:24:36 -07:00
parent edbfc2348a
commit 184f1fa631
10 changed files with 234 additions and 14 deletions

View file

@ -10,6 +10,7 @@ const defaultSettings = {
simplifiedControls: false,
logAppDetails: true,
defaultPage: "home",
cairoAuth: null,
};
const settings = localSettings ? JSON.parse(localSettings) : defaultSettings;
@ -27,6 +28,7 @@ const settingsUpdater = (oldState, settingsUpdate) => {
if (settingsUpdate[k] === undefined) continue;
settingsToUpdate[k] = settingsUpdate[k];
}
console.log("SAVING", settingsToUpdate);
localStorage.setItem("settings", JSON.stringify(settingsToUpdate));
};

View file

@ -5,9 +5,13 @@ import Button from "@mui/material/Button";
import SpeedDialIcon from "@mui/material/SpeedDialIcon";
// Import Navbar
/*import Navbar from "./Navbar.jsx";*/
import { useCairoAuth } from "@mcl/util/auth.js";
import MCLMenu from "./MCLMenu.jsx";
import Auth from "@mcl/pages/Auth.jsx";
export default function Views() {
const auth = useCairoAuth();
if (!auth) return <Auth />;
return (
<div className="view">
<MCLMenu />

63
src/pages/Auth.jsx Normal file
View file

@ -0,0 +1,63 @@
import { useState, useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography";
export default function Auth() {
const [searchParams] = useSearchParams();
const currentServer = searchParams.get("token");
const nav = useNavigate();
const cairoLogin = () =>
(window.location.href = `/api/auth/redirect?redirectUri=${window.location.href}`);
return (
<Box
className="auth"
sx={{
height: "100%",
backgroundColor: (theme) => theme.palette.primary.main,
}}
>
<Box className="auth-display" sx={{ display: "flex", height: "95vh" }}>
<Box
sx={{
height: "50%",
width: "50%",
m: "auto",
display: "flex",
flexWrap: "wrap",
}}
>
<Box
sx={{
backgroundColor: "white",
display: "inline-flex",
m: "auto",
borderRadius: "8px",
height: "5rem",
}}
>
<Button
color="secondary"
variant="outlined"
onClick={cairoLogin}
sx={{ p: "1.5rem" }}
endIcon={
<img
src="https://cairo.dunemask.net/cairo/icons/apple-touch-icon-120x120.png"
width="48px"
style={{ borderRadius: "4px" }}
/>
}
>
Login with Cairo
</Button>
</Box>
</Box>
</Box>
</Box>
);
}

56
src/util/auth.js Normal file
View file

@ -0,0 +1,56 @@
import { useState, useContext, useEffect } from "react";
import { useSearchParams, useNavigate } from "react-router-dom";
import SettingsContext from "@mcl/settings";
const verifyAuth = (authToken) =>
fetch("/api/auth/verify", {
headers: { Authorization: `Bearer ${authToken}` },
})
.then((res) => res.status === 200)
.catch(() => false);
export function useCairoAuth() {
const { state: settings, updateSettings } = useContext(SettingsContext);
const [auth, setAuth] = useState(!!settings.cairoAuth);
const [searchParams] = useSearchParams();
const nav = useNavigate();
useEffect(() => {
const webToken = searchParams.get("cairoAuthToken");
if (!webToken) return;
verifyAuth(webToken).then(setAuth);
updateSettings({ cairoAuth: webToken });
nav("/");
}, [searchParams]);
useEffect(() => {
verifyAuth(settings.cairoAuth).then(setAuth);
nav("/");
}, [settings.cairoAuth]);
return auth;
}
export function useAuth() {
const { state: settings } = useContext(SettingsContext);
const [auth, setAuth] = useState(!!!settings.cairoAuth);
if (!settings.cairoAuth) return auth;
fetch("/api/auth/verify", {
headers: { Authorization: `Bearer ${settings.cairoAuth}` },
})
.then(() => setAuth(true))
.catch(() => setAuth(false));
return auth;
}
export function useUpdateAuth() {
const { updateSettings } = useContext(SettingsContext);
const [searchParams] = useSearchParams();
const webToken = searchParams.get("cairoAuthToken");
if (webToken) {
updateSettings({ cairoAuth: webToken });
searchParams.delete("cairoAuthToken");
}
}