diff --git a/package.json b/package.json index c6c48c1..32f38f2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "private": false, "name": "bluelib", - "version": "0.11.6", + "version": "0.12.0", "license": "AGPL-3.0-or-later", "source": "src/index.js", "main": "dist/index.js", diff --git a/src/contexts/RoyalnetLoginStatus.js b/src/contexts/RoyalnetLoginStatus.js new file mode 100644 index 0000000..cb08da1 --- /dev/null +++ b/src/contexts/RoyalnetLoginStatus.js @@ -0,0 +1,3 @@ +import { createContext } from 'preact'; + +export default createContext(null); diff --git a/src/hooks/useLoginDataStorage.js b/src/hooks/useLoginDataStorage.js new file mode 100644 index 0000000..160838d --- /dev/null +++ b/src/hooks/useLoginDataStorage.js @@ -0,0 +1,55 @@ +import { useEffect, useState } from 'preact/hooks'; +import { royalnetApiRequest } from '../utils/royalnetApiRequest'; +import { route } from 'preact-router'; + +export default function(defaultInstanceUrl) { + const [instanceUrl, setInstanceUrl] = useState(defaultInstanceUrl); + const [loginStatus, setLoginStatus] = useState(null); + + useEffect(() => { + console.debug("Checking if an instanceUrl is stored in the localStorage..."); + let instanceUrlStore = window.localStorage.getItem("instanceUrl"); + if(instanceUrlStore === null) return; + console.debug(`Found instanceUrl ${instanceUrlStore}, setting it...`); + setInstanceUrl(instanceUrlStore); + console.debug("Checking if a valid login token is stored in the localStorage..."); + let loginStatusStore = JSON.parse(window.localStorage.getItem("loginStatus")); + if(loginStatusStore === null) return; + console.debug("Found a login token; checking its validity..."); + royalnetApiRequest(instanceUrlStore, "GET", "/api/auth/token/v1", {token: loginStatusStore.token}).then((data => { + let expiration = new Date(data.expiration); + console.debug(`Login token expires: ${expiration}`); + let now = new Date(); + if(expiration >= now ) { + console.debug(`Login token is valid, logging in...`); + setLoginStatus(data); + console.debug(`Successfully logged in as ${data.user.username} @ ${instanceUrlStore} !`); + } + else { + console.debug(`Login token has expired, clearing...`); + window.localStorage.setItem("loginStatus", null); + } + })).catch((err) => { + console.error(`Could not check validity of the login token: ${err}`) + }) + }, []); + + function onSuccessfulLogin(newInstanceUrl, newLoginStatus) { + console.debug(`Successfully logged in as ${newLoginStatus.user.username} @ ${newInstanceUrl} !`); + setInstanceUrl(newInstanceUrl); + setLoginStatus(newLoginStatus); + console.debug("Saving login data in the localStorage..."); + window.localStorage.setItem("instanceUrl", newInstanceUrl); + window.localStorage.setItem("loginStatus", JSON.stringify(newLoginStatus)); + route("/"); + } + + function requestLogout() { + console.debug("User requested logout, clearing loginStatus and localStorage..."); + setLoginStatus(null); + window.localStorage.setItem("loginStatus", null); + route("/"); + } + + return [instanceUrl, loginStatus, onSuccessfulLogin, requestLogout] +} diff --git a/src/hooks/useRoyalnetData.js b/src/hooks/useRoyalnetData.js index cb70ba3..a931700 100644 --- a/src/hooks/useRoyalnetData.js +++ b/src/hooks/useRoyalnetData.js @@ -1,14 +1,24 @@ import RoyalnetInstanceUrl from '../contexts/RoyalnetInstanceUrl'; +import LoginStatus from "../contexts/RoyalnetLoginStatus"; import {useContext, useState} from 'preact/hooks'; -import {royalnetApiRequest} from '../utils/royalnetApiRequest'; import useDeepCompareEffect from "use-deep-compare-effect"; +import {royalnetApiRequest} from '../utils/royalnetApiRequest'; export default function(method, path, body) { const instanceUrl = useContext(RoyalnetInstanceUrl); + const loginStatus = useContext(LoginStatus); const [data, setData] = useState(undefined); const [error, setError] = useState(undefined); + if(body === undefined) { + body = {} + } + + if(loginStatus !== null) { + body["token"] = loginStatus["token"] + } + function refresh() { setData(undefined); setError(undefined); diff --git a/src/index.js b/src/index.js index 2e70a15..2af8fb8 100644 --- a/src/index.js +++ b/src/index.js @@ -22,8 +22,10 @@ import LatexDefaultDisplay from "./contexts/LatexDefaultDisplay"; import LatexDefaultInline from "./contexts/LatexDefaultInline"; import LatexRenderColor from "./contexts/LatexRenderColor"; import RoyalnetInstanceUrl from "./contexts/RoyalnetInstanceUrl"; +import RoyalnetLoginStatus from "./contexts/RoyalnetLoginStatus"; import useFormValidator from "./hooks/useFormValidator"; +import useLoginDataStorage from "./hooks/useLoginDataStorage"; import useRoyalnetData from "./hooks/useRoyalnetData"; import useRoyalnetInstanceValidator from "./hooks/useRoyalnetInstanceValidator"; @@ -62,8 +64,10 @@ export { LatexDefaultInline, LatexRenderColor, RoyalnetInstanceUrl, + RoyalnetLoginStatus, useFormValidator, + useLoginDataStorage, useRoyalnetData, useRoyalnetInstanceValidator,