Skip to content
Snippets Groups Projects
App.js 2.58 KiB
Newer Older
  • Learn to ignore specific revisions
  • import React, { useEffect, useState } 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");
      const [timerID, setTimerID] = useState(null);
    
    meskio's avatar
    meskio committed
    
    
      useEffect(() => {
        if (!timerID) {
          startRenew(token, setToken, setTimerID);
        }
    
    meskio's avatar
    meskio committed
        return () => stopRenew(timerID);
    
      }, [token, setToken, timerID, setTimerID]);
    
      const login = (newToken, member) => {
        setNum(member.num);
        setRole(member.role);
        setToken(newToken);
        startRenew(newToken, setToken, setTimerID);
      };
    
      const logout = () => {
        setNum("");
        setRole("");
        setToken("");
        stopRenew(timerID);
      };
    
      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, setToken) {
      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((data) => {
          const token = data.token;
          setToken(token);
        })
        .catch((error) => {
    
          if (error instanceof ResponseError && error.response.status === 401) {
    
    meskio's avatar
    meskio committed
            setToken("");
    
          } else {
            console.log("Error renewing token: " + error.message);
          }
    
    meskio's avatar
    meskio committed
        });
    
    meskio's avatar
    meskio committed
    
    
    function startRenew(token, setToken, setTimerID) {
      if (token && getClaims(token)["exp"] !== undefined) {
        const timerID = setInterval(
          () => renewToken(token, setToken),
          60000 // every minute
        );
        setTimerID(timerID);
    
    meskio's avatar
    meskio committed
      }
    
    meskio's avatar
    meskio committed
    
    
    function stopRenew(timerID) {
      if (timerID) {
        clearInterval(timerID);
    
    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;