// Note: Based on https://usehooks.com/useAuth/ import React, { useState, useContext, createContext, ReactFragment } from "react"; import PersonIcon from '@material-ui/icons/Person'; import * as serverApi from '../api'; export interface AuthUser { id: number, email: string, icon: ReactFragment, } export interface Auth { user: AuthUser | null, signout: () => void, signin: (email: string, password: string) => Promise, signup: (email: string, password: string) => Promise, }; const authContext = createContext({ user: null, signout: () => { }, signin: (email: string, password: string) => { throw new Error("Auth object not initialized."); }, signup: (email: string, password: string) => { throw new Error("Auth object not initialized."); }, }); export function ProvideAuth(props: { children: any }) { const auth = useProvideAuth(); return {props.children}; } export const useAuth = () => { return useContext(authContext); }; function persistAuth(auth: AuthUser | null) { let s = window.sessionStorage; if(auth === null) { s.removeItem('userId'); s.removeItem('userEmail'); return; } s.setItem('userId', auth.id.toString()); s.setItem('userEmail', auth.email); // TODO icon } function loadAuth(): AuthUser | null { let s = window.sessionStorage; let id = s.getItem('userId'); let email = s.getItem('userEmail'); if (id && email) { return { id: parseInt(id), email: email, icon: } } return null; } function useProvideAuth() { const [user, setUser] = useState(loadAuth()); // TODO: password maybe shouldn't be encoded into the URL. const signin = (email: string, password: string) => { return (async () => { const urlBase = (process.env.REACT_APP_BACKEND || "") + serverApi.LoginEndpoint; const url = `${urlBase}?username=${encodeURIComponent(email)}&password=${encodeURIComponent(password)}`; const response = await fetch(url, { method: "POST" }); const json = await response.json(); if (!("userId" in json)) { throw new Error("No UserID received from login."); } const user = { id: json.userId, email: email, icon: , } setUser(user); persistAuth(user); return user; })(); }; const signup = (email: string, password: string) => { return (async () => { const requestOpts = { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: email, password: password, }) }; const response = await fetch((process.env.REACT_APP_BACKEND || "") + serverApi.RegisterUserEndpoint, requestOpts) if (!response.ok) { throw new Error("Failed to register user.") } })(); }; const signout = () => { console.log("Signing out."); setUser(null); persistAuth(null); return (async () => { const url = (process.env.REACT_APP_BACKEND || "") + serverApi.LogoutEndpoint; const response = await fetch(url, { method: "POST" }); if (!response.ok) { throw new Error("Failed to log out."); } })(); }; // Return the user object and auth methods return { user, signin, signup, signout, }; }