Skip to content
Snippets Groups Projects
App.js 3.28 KiB
Newer Older
  • Learn to ignore specific revisions
  • import React, { useEffect, useState } from "react";
    import { Preferences } from "@capacitor/preferences";
    
    import Panel from "./Panel";
    
    meskio's avatar
    meskio committed
    import AuthContext from "./AuthContext";
    
    import { ResponseError } from "./errors";
    
    meskio's avatar
    meskio committed
    import { url } from "./util";
    
    meskio's avatar
    meskio committed
    function useStorageItem(key, fromString) {
    
      const [storedValue, setStoredValue] = useState();
    
      useEffect(() => {
        async function loadValue() {
          try {
            const result = await Preferences.get({ key });
    
    meskio's avatar
    meskio committed
            if (result.value != null) {
              const value = fromString ? fromString(result.value) : result.value;
              setStoredValue(value);
    
            } else {
              setStoredValue(undefined);
            }
          } catch (e) {
            return undefined;
          }
        }
        loadValue();
    
    meskio's avatar
    meskio committed
      }, [setStoredValue, key, fromString]);
    
    
      const setValue = async (value) => {
        try {
          setStoredValue(value);
          await Preferences.set({
            key,
            value,
          });
        } catch (e) {
          console.error(e);
        }
      };
    
      return [storedValue, setValue];
    }
    
    
    function App() {
    
    meskio's avatar
    meskio committed
      const [num, setNum] = useStorageItem("num", Number);
    
      const [role, setRole] = useStorageItem("role");
      const [token, setToken] = useStorageItem("token");
    
    meskio's avatar
    meskio committed
      const [disabled, setDisabled] = useStorageItem(
        "disabled",
        (value) => value === "true"
      );
    
    meskio's avatar
    meskio committed
    
    
      useEffect(() => {
    
        const setTokenData = (data) => {
          setToken(data.token);
          setRole(data.role);
    
    meskio's avatar
    meskio committed
          setDisabled(data.disabled);
    
        };
    
        const timerID = window.setInterval(
          () => renewToken(token, setTokenData),
          60000 // every minute
        );
        return () => window.clearInterval(timerID);
    
    meskio's avatar
    meskio committed
      }, [token, setToken, setRole, setDisabled]);
    
    
      const login = (newToken, member) => {
        setNum(member.num);
        setRole(member.role);
    
    meskio's avatar
    meskio committed
        setDisabled(member.disabled);
    
        setToken(newToken);
      };
    
      const logout = () => {
    
    meskio's avatar
    meskio committed
        setNum(null);
        setRole(null);
        setDisabled(null);
        setToken(null);
    
        Preferences.clear();
    
    meskio's avatar
    meskio committed
      const value = { num, role, disabled, token };
    
    meskio's avatar
    meskio committed
      return (
    
        <AuthContext.Provider value={value}>
          <Panel onLogin={login} onLogout={logout} isLogged={isLoggedIn(token)} />
        </AuthContext.Provider>
    
    meskio's avatar
    meskio committed
    function getClaims(token) {
    
    meskio's avatar
    meskio committed
      const base64Url = token.split(".")[1];
      const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
      const jsonPayload = decodeURIComponent(
        atob(base64)
          .split("")
          .map(function (c) {
            return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
          })
          .join("")
      );
    
    meskio's avatar
    meskio committed
    
    
    meskio's avatar
    meskio committed
      return JSON.parse(jsonPayload);
    
    meskio's avatar
    meskio committed
    }
    
    
    function renewToken(oldToken, setTokenData) {
      if (!oldToken) {
        return;
      }
    
    
      fetch(url("/api/token"), {
        headers: { "x-authentication": oldToken },
      })
        .then((response) => {
          if (!response.ok) {
    
            throw new ResponseError(response);
    
    meskio's avatar
    meskio committed
          }
    
          return response.json();
        })
    
        .then(setTokenData)
    
        .catch((error) => {
    
          if (error instanceof ResponseError && error.response.status === 401) {
    
            setTokenData({ token: "", role: "" });
    
          } else {
            console.log("Error renewing token: " + error.message);
          }
    
    meskio's avatar
    meskio committed
        });
    
    meskio's avatar
    meskio committed
    
    
    function isLoggedIn(token) {
      if (!token) {
        return false;
    
    meskio's avatar
    meskio committed
      }
    
      const claims = getClaims(token);
      if (claims["exp"] === undefined) {
        return true;
    
    meskio's avatar
    meskio committed
      }
    
      return claims["exp"] > Date.now() / 1000;
    
    }
    
    export default App;