101 lines
2.5 KiB
React
101 lines
2.5 KiB
React
![]() |
import React, { useEffect, useState } from "react";
|
||
|
|
||
|
import {
|
||
|
createUser as registerApi,
|
||
|
isLoggedIn,
|
||
|
login as loginApi,
|
||
|
logout as logoutApi,
|
||
|
} from "../api";
|
||
|
import { useQuery } from "../hooks";
|
||
|
|
||
|
import { useLocation, useNavigate } from "react-router-dom";
|
||
|
|
||
|
const initState = {
|
||
|
user: undefined,
|
||
|
};
|
||
|
|
||
|
export const AuthenticationContext = React.createContext({
|
||
|
...initState,
|
||
|
login: () => {},
|
||
|
register: () => {},
|
||
|
logout: () => {},
|
||
|
});
|
||
|
|
||
|
export const AuthenticationProvider = ({ children }) => {
|
||
|
const navigate = useNavigate();
|
||
|
const location = useLocation();
|
||
|
const query = useQuery();
|
||
|
const [authState, setAuthState] = useState(initState);
|
||
|
const [isLoading, setIsLoading] = useState(true);
|
||
|
|
||
|
const redirect = () => {
|
||
|
navigate(query.get("redirect_uri") || "/");
|
||
|
};
|
||
|
|
||
|
const login = async (email, password) => {
|
||
|
loginApi(email, password)
|
||
|
.then((user) => {
|
||
|
setAuthState({ user });
|
||
|
redirect();
|
||
|
})
|
||
|
.catch(() => {
|
||
|
setAuthState({ user: undefined });
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const register = async (username, password, confirmation) => {
|
||
|
registerApi(username, password, confirmation).then((user) => {
|
||
|
setAuthState({ user });
|
||
|
redirect();
|
||
|
});
|
||
|
};
|
||
|
|
||
|
const logout = () => {
|
||
|
logoutApi().then(() => {
|
||
|
setAuthState(initState);
|
||
|
navigate(`/login`);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
useEffect(() => {
|
||
|
isLoggedIn()
|
||
|
.then((user) => {
|
||
|
if (user === "Unauthorized") throw new Error("Unauthorized");
|
||
|
setAuthState({ user });
|
||
|
if (location.pathname === "/login") {
|
||
|
redirect();
|
||
|
}
|
||
|
})
|
||
|
.catch(() => {
|
||
|
setAuthState({ user: undefined });
|
||
|
|
||
|
if (!location.pathname.match(/^(\/|\/login|\/register)$/)) {
|
||
|
navigate(
|
||
|
`/login?redirect_uri=${encodeURI(location.pathname)}`
|
||
|
);
|
||
|
}
|
||
|
})
|
||
|
.finally(() => {
|
||
|
setIsLoading(false);
|
||
|
});
|
||
|
}, []);
|
||
|
|
||
|
useEffect(() => {
|
||
|
if (location.pathname === "/logout") {
|
||
|
logout();
|
||
|
}
|
||
|
}, [location]);
|
||
|
|
||
|
if (isLoading) {
|
||
|
return <p>Loading...</p>;
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<AuthenticationContext.Provider
|
||
|
value={{ ...authState, login, logout, register }}
|
||
|
>
|
||
|
{children}
|
||
|
</AuthenticationContext.Provider>
|
||
|
);
|
||
|
};
|