2021-04-26 20:08:52 +00:00
|
|
|
import React, { useCallback, useContext } from "react"
|
2021-04-29 14:58:31 +00:00
|
|
|
import useLocalStorageState from "../../hooks/useLocalStorageState"
|
|
|
|
import ContextServer from "../../contexts/ContextServer"
|
|
|
|
import ContextUser from "../../contexts/ContextUser"
|
2021-04-26 16:36:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides {@link ContextUser} to all contained elements.
|
|
|
|
*
|
|
|
|
* @param children
|
|
|
|
* @returns {JSX.Element}
|
|
|
|
* @constructor
|
|
|
|
*/
|
|
|
|
export default function GlobalUser({ children }) {
|
|
|
|
const {fetchData} = useContext(ContextServer)
|
|
|
|
const [user, setUser] = useLocalStorageState("login", null)
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Fetch JSON data from the API as the authenticated user.
|
|
|
|
*
|
|
|
|
* Requires an user to be logged in!
|
|
|
|
*
|
|
|
|
* @param method - The method to use.
|
|
|
|
* @param path - The path to request data at (ex. `/api/repositories`)
|
|
|
|
* @param body - The body of the request (it will be automatically converted to JSON.
|
|
|
|
* @param init - Additional arguments to pass to the `init` parameter of {@link fetch}.
|
|
|
|
* @returns {Promise<*>}
|
|
|
|
*/
|
2021-04-26 20:08:52 +00:00
|
|
|
const fetchDataAuth = useCallback(async (method, path, body, init) => {
|
2021-04-26 16:36:41 +00:00
|
|
|
if(!user) {
|
|
|
|
throw new Error("Not logged in")
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!init) {
|
|
|
|
init = {}
|
|
|
|
}
|
|
|
|
if(!init["headers"]) {
|
|
|
|
init["headers"] = {}
|
|
|
|
}
|
|
|
|
init["headers"]["Authorization"] = `Bearer ${user["token"]}`
|
|
|
|
|
2021-04-26 20:08:52 +00:00
|
|
|
return await fetchData(method, path, body, init)
|
|
|
|
}, [fetchData, user])
|
2021-04-26 16:36:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Try to login to the active server with the passed credentials.
|
|
|
|
*
|
|
|
|
* @param email - The user's email.
|
|
|
|
* @param password - The user's password.
|
|
|
|
* @returns {Promise<void>}
|
|
|
|
*/
|
2021-04-26 20:08:52 +00:00
|
|
|
const login = useCallback(async (email, password) => {
|
2021-04-26 16:36:41 +00:00
|
|
|
console.debug("Contacting server to login...")
|
|
|
|
const data = await fetchData("POST", `/api/login`, {
|
|
|
|
"email": email,
|
|
|
|
"password": password,
|
|
|
|
})
|
|
|
|
|
|
|
|
console.debug("Storing login state...")
|
|
|
|
setUser({
|
|
|
|
email: data["user"]["email"],
|
|
|
|
isAdmin: data["user"]["isAdmin"],
|
|
|
|
username: data["user"]["username"],
|
|
|
|
token: data["access_token"],
|
|
|
|
})
|
|
|
|
|
|
|
|
console.info("Login successful!")
|
2021-04-26 20:08:52 +00:00
|
|
|
}, [fetchData, setUser])
|
2021-04-26 16:36:41 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Logout from the currently active server.
|
|
|
|
*/
|
2021-04-26 20:08:52 +00:00
|
|
|
const logout = useCallback(() => {
|
2021-04-26 16:36:41 +00:00
|
|
|
console.debug("Clearing login state...")
|
|
|
|
setUser(null)
|
|
|
|
console.debug("Cleared login state!")
|
|
|
|
|
|
|
|
console.info("Logout successful!")
|
2021-04-26 20:08:52 +00:00
|
|
|
}, [setUser])
|
2021-04-26 16:36:41 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
<ContextUser.Provider value={{user, login, logout, fetchDataAuth}}>
|
|
|
|
{children}
|
|
|
|
</ContextUser.Provider>
|
|
|
|
)
|
|
|
|
}
|