Skip to content
Snippets Groups Projects
App.js 2.28 KiB
Newer Older
  • Learn to ignore specific revisions
  • import React, { useEffect } from "react";
    
    import { useStorageItem } from "@capacitor-community/react-hooks/storage";
    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";
    
    function App() {
      const [num, setNum] = useStorageItem("num");
      const [role, setRole] = useStorageItem("role");
      const [token, setToken] = useStorageItem("token");
    
    meskio's avatar
    meskio committed
    
    
      useEffect(() => {
    
        const setTokenData = (data) => {
          setToken(data.token);
          setRole(data.role);
        };
    
        const timerID = window.setInterval(
          () => renewToken(token, setTokenData),
          60000 // every minute
        );
        return () => window.clearInterval(timerID);
      }, [token, setToken, setRole]);
    
    
      const login = (newToken, member) => {
        setNum(member.num);
        setRole(member.role);
        setToken(newToken);
      };
    
      const logout = () => {
        setNum("");
        setRole("");
        setToken("");
      };
    
      const value = { num, role, 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;