LinkList/frontend/components/Login/authcontext.tsx

72 lines
1.5 KiB
TypeScript

import React, { useState, useContext, createContext } from "react";
interface LoggedInState {
loggedIn: true;
headers: HeadersInit;
logout(): void;
}
interface LoggedOutState {
loggedIn: false;
login(password: string): Promise<boolean>;
}
export type AuthState = LoggedInState | LoggedOutState;
const AuthContext = createContext({
loggedIn: false,
login: () => {
throw new Error("No parent AuthContext found!");
},
} as AuthState);
export const AuthProvider: React.FC = (props) => {
const [loggedIn, setLoggedIn] = useState(false);
const [headers, setHeaders] = useState<HeadersInit | undefined>();
function logout() {
setLoggedIn(false);
setHeaders(undefined);
}
async function login(password: string): Promise<boolean> {
const username = process.env.NEXT_PUBLIC_EDITOR_USERNAME;
if (!username) {
throw new Error(
"Missing NEXT_PUBLIC_EDITOR_USERNAME environment variable"
);
}
const newHeaders = {
Authorization: `CustomBasic ${btoa(`${username}:${password}`)}`,
};
const res = await fetch("/api/editor/links", { headers: newHeaders });
if (res.status === 200) {
setLoggedIn(true);
setHeaders(newHeaders);
return true;
} else {
logout();
return false;
}
}
return (
<AuthContext.Provider
value={
loggedIn && headers != null
? { loggedIn, headers, logout }
: { loggedIn: false, login }
}
{...props}
/>
);
};
export function useAuth(): AuthState {
return useContext(AuthContext);
}