@trap_stevo/legendarybuilderproreact-ui
Version:
The legendary UI & utility API that makes your application a legendary application. ~ Created by Steven Compton
895 lines (882 loc) • 37.8 kB
JavaScript
import _typeof from "@babel/runtime/helpers/typeof";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
import _regeneratorRuntime from "@babel/runtime/regenerator";
/*
Created by Hassan Steven Compton.
March 7, 2024.
*/
import React, { createContext, useContext, useState, useEffect, useRef, useMemo, useCallback } from "react";
import { generateIdentityKey, getCryptoKey, encryptData, decryptData } from "../HUDManagers/HUDUniversalEncryptionUtilitiesManager.js";
import { UpdateObject } from "../HUDManagers/HUDUniversalHUDUtilityManager.js";
var AuthContext = /*#__PURE__*/createContext();
/**
* AuthProvider provides user authentication encapsulation within an application;
* keeping track of user credentials and user authenticated state.
*
* @component
*
* @param {boolean} [saveSessionCacheOnTimeout=false] - Determines whether to save session cache on timeout.
* @param {number} [signedSessionTimeout=18000] - Session timeout in seconds. Default is 5 hours.
* @param {number} [sessionCheckInterval=1000] - How often (in milliseconds) to check for session expiration.
* @param {Array} [keysToClearOnTimeout=[]] - List of keys to clear from session cache on timeout.
* @param {boolean} [autoSignIn=false] - Determines whether to automatically sign in the user if session data is found in localStorage.
* @param {boolean} [useAbsoluteExpiration=false] - Whether to use absolute expiration timestamp instead of session duration.
* @param {string} [signedUserExpirationKey=null] - Key in signedUser object for token-based absolute expiration (e.g. "expiresAt").
* @param {number} [sessionWarningThreshold=300] - Time (in seconds) to trigger onSessionTimeWarning.
* @param {function} [onSessionTimeWarning] - Callback triggered when time left is under threshold.
*
* @param {boolean} [shouldExtendSessionOnActivity=true] - Automatically extend the session when user activity is detected.
* @param {number} [sessionExtensionThreshold=300000] - Remaining time threshold (in ms) under which session auto-extension is triggered.
* @param {number} [minExtendInterval=20000] - Minimum interval (in ms) between successive auto-extension attempts.
*
* @param {function} [onSessionExpire] - Callback triggered when the session fully expires.
* @param {function} [onSessionRenew] - Callback triggered whenever the session is successfully renewed.
*
* @param {function} [onEncryptionError] - Callback for handling errors during encryption/decryption.
* @param {function} [getExpiryTs] - Custom function to resolve session expiration timestamp dynamically.
* @param {function} [extendSession] - Custom function to handle session extension logic.
*
* @param {boolean} [encryptAuthIdentity=false] - Enables persistent encryption of signed user identity.
* @param {number} [identityDepth=100000] - PBKDF2 iteration depth for deriving crypto key.
* @param {string} [identitySeed] - Optional passphrase for key derivation.
* @param {string} [identityOffset] - Optional salt for key derivation.
*
* @param {React.ReactNode} children - The content wrapped by this component.
* @returns {JSX.Element} The AuthProvider component encapsulating children with authentication context.
*/
export var AuthProvider = function AuthProvider(_ref) {
var _ref$saveSessionCache = _ref.saveSessionCacheOnTimeout,
saveSessionCacheOnTimeout = _ref$saveSessionCache === void 0 ? false : _ref$saveSessionCache,
_ref$signedSessionTim = _ref.signedSessionTimeout,
signedSessionTimeout = _ref$signedSessionTim === void 0 ? 18000 : _ref$signedSessionTim,
_ref$sessionCheckInte = _ref.sessionCheckInterval,
sessionCheckInterval = _ref$sessionCheckInte === void 0 ? 1000 : _ref$sessionCheckInte,
_ref$keysToClearOnTim = _ref.keysToClearOnTimeout,
keysToClearOnTimeout = _ref$keysToClearOnTim === void 0 ? [] : _ref$keysToClearOnTim,
_ref$autoSignIn = _ref.autoSignIn,
autoSignIn = _ref$autoSignIn === void 0 ? false : _ref$autoSignIn,
_ref$useAbsoluteExpir = _ref.useAbsoluteExpiration,
useAbsoluteExpiration = _ref$useAbsoluteExpir === void 0 ? false : _ref$useAbsoluteExpir,
_ref$signedUserExpira = _ref.signedUserExpirationKey,
signedUserExpirationKey = _ref$signedUserExpira === void 0 ? null : _ref$signedUserExpira,
_ref$sessionWarningTh = _ref.sessionWarningThreshold,
sessionWarningThreshold = _ref$sessionWarningTh === void 0 ? 300 : _ref$sessionWarningTh,
_ref$shouldExtendSess = _ref.shouldExtendSessionOnActivity,
shouldExtendSessionOnActivity = _ref$shouldExtendSess === void 0 ? true : _ref$shouldExtendSess,
_ref$sessionExtension = _ref.sessionExtensionThreshold,
sessionExtensionThreshold = _ref$sessionExtension === void 0 ? 5 * 60 * 1000 : _ref$sessionExtension,
_ref$minExtendInterva = _ref.minExtendInterval,
minExtendInterval = _ref$minExtendInterva === void 0 ? 20 * 1000 : _ref$minExtendInterva,
_ref$onSessionTimeWar = _ref.onSessionTimeWarning,
onSessionTimeWarning = _ref$onSessionTimeWar === void 0 ? null : _ref$onSessionTimeWar,
_ref$onSessionExpire = _ref.onSessionExpire,
onSessionExpire = _ref$onSessionExpire === void 0 ? null : _ref$onSessionExpire,
_ref$onSessionRenew = _ref.onSessionRenew,
onSessionRenew = _ref$onSessionRenew === void 0 ? null : _ref$onSessionRenew,
_ref$onEncryptionErro = _ref.onEncryptionError,
onEncryptionError = _ref$onEncryptionErro === void 0 ? null : _ref$onEncryptionErro,
_ref$getExpiryTs = _ref.getExpiryTs,
getExpiryTs = _ref$getExpiryTs === void 0 ? null : _ref$getExpiryTs,
_ref$extendSession = _ref.extendSession,
extendSession = _ref$extendSession === void 0 ? null : _ref$extendSession,
_ref$encryptAuthIdent = _ref.encryptAuthIdentity,
encryptAuthIdentity = _ref$encryptAuthIdent === void 0 ? false : _ref$encryptAuthIdent,
_ref$identityDepth = _ref.identityDepth,
identityDepth = _ref$identityDepth === void 0 ? 100000 : _ref$identityDepth,
identitySeed = _ref.identitySeed,
identityOffset = _ref.identityOffset,
children = _ref.children;
var resolvedSeed = useMemo(function () {
if (identitySeed) {
return identitySeed;
}
var existing = localStorage.getItem("_session_identity_seed");
if (existing) {
return existing;
}
var key = generateIdentityKey();
localStorage.setItem("_session_identity_seed", key);
return key;
}, [identitySeed]);
var resolvedOffset = useMemo(function () {
if (identityOffset) {
return identityOffset;
}
var existing = localStorage.getItem("_session_identity_offset");
if (existing) {
return existing;
}
var key = generateIdentityKey();
localStorage.setItem("_session_identity_offset", key);
return key;
}, [identityOffset]);
/**
* Initializes the current signed state from cache.
*
* @function
* @name currentSignedState
* @returns {Object} The current signed user and signed-in status.
*/
var currentSignedState = useCallback(function () {
var savedUser = localStorage.getItem("SignedUserCredential");
var userSignedIn = localStorage.getItem("UserSignedIn");
return {
currentSignedUser: savedUser,
currentSignedIn: userSignedIn ? JSON.parse(userSignedIn) : false
};
}, []);
var _useState = useState(shouldExtendSessionOnActivity),
_useState2 = _slicedToArray(_useState, 2),
autoExtendOnActivity = _useState2[0],
setAutoExtendOnActivity = _useState2[1];
/**
* Responsible for the user's credentials.
*
* @type {Object}
*/
var _useState3 = useState({}),
_useState4 = _slicedToArray(_useState3, 2),
signedUser = _useState4[0],
setSignedUser = _useState4[1];
/**
* Allows for checking the user's authentication state.
*
* @type {boolean}
*/
var _useState5 = useState(function () {
return currentSignedState().currentSignedIn;
}),
_useState6 = _slicedToArray(_useState5, 2),
signedIn = _useState6[0],
setSignedIn = _useState6[1];
var extendFnRef = useRef(extendSession || null);
var getExpiryRef = useRef(getExpiryTs || null);
var sessionRenewalEnabledRef = useRef(true);
var sessionInitialized = useRef(false);
var lastExtendAtRef = useRef(0);
/**
* Synchronizes the current state to the cache.
*
* @function
* @name syncStateToCache
* @param {Object} user - The user's credentials.
* @param {boolean} signedIn - The user's signed-in status.
*/
var syncStateToCache = useCallback( /*#__PURE__*/function () {
var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(user, signedIn) {
var now, encrypted, expiresAt;
return _regeneratorRuntime.wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
now = Date.now();
if (!(encryptAuthIdentity && resolvedSeed && resolvedOffset)) {
_context.next = 14;
break;
}
_context.prev = 2;
_context.next = 5;
return encryptData(user, resolvedSeed, resolvedOffset, identityDepth);
case 5:
encrypted = _context.sent;
localStorage.setItem("SignedUserCredential", encrypted);
_context.next = 12;
break;
case 9:
_context.prev = 9;
_context.t0 = _context["catch"](2);
if (onEncryptionError) {
onEncryptionError(_context.t0);
}
case 12:
_context.next = 15;
break;
case 14:
localStorage.setItem("SignedUserCredential", JSON.stringify(user));
case 15:
localStorage.setItem("UserSignedIn", JSON.stringify(signedIn));
localStorage.setItem("SignedSessionStart", now.toString());
localStorage.setItem("SignedSessionTimeout", signedSessionTimeout.toString());
if (!useAbsoluteExpiration) {
_context.next = 22;
break;
}
expiresAt = now + signedSessionTimeout * 1000;
localStorage.setItem("SignedSessionExpiresAt", expiresAt.toString());
return _context.abrupt("return");
case 22:
if (!localStorage.getItem("SignedSessionStart")) {
localStorage.setItem("SignedSessionStart", now.toString());
}
case 23:
case "end":
return _context.stop();
}
}, _callee, null, [[2, 9]]);
}));
return function (_x, _x2) {
return _ref2.apply(this, arguments);
};
}(), [encryptAuthIdentity, onEncryptionError, resolvedSeed, resolvedOffset, identityDepth, signedSessionTimeout, useAbsoluteExpiration]);
/**
* Signs in user.
*
* @function
* @name signIn
* @description Sets the user's authentication state to true.
*/
var signIn = useCallback(function () {
setSignedIn(true);
}, []);
/**
* Signs out the user and manages session cache.
*
* @function
* @name signOut
* @param {boolean} [saveSessionCache=false] - Whether to preserve the entire session cache.
* @param {string[]} [preserveKeys=["AuthenticatedOnWebApp"]] - Keys to keep when clearing the cache.
* @param {string[]} [keysToClear=[]] - Specific keys to remove from the cache.
* @param {Object} [options={}] - Optional configuration for cache handling and callbacks.
* @returns {Object} Result object containing:
* @returns {boolean} result.ok - Indicates success.
* @returns {string} result.reason - Reason or status message.
* @returns {string[]} result.preservedKeys - Keys that were preserved.
* @returns {string[]} result.clearedKeys - Keys that were cleared.
* @returns {Object|null} result.cacheBefore - Cache snapshot before sign-out.
* @returns {Object|null} result.cacheAfter - Cache snapshot after sign-out.
*/
var signOut = useCallback(function () {
var saveSessionCache = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
var keysToClear = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
var preserveKeys = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
var _ref3 = options || {},
clearFromSessionCache = _ref3.clearFromSessionCache,
updateSessionCache = _ref3.updateSessionCache,
clearSessionCache = _ref3.clearSessionCache,
getSessionCache = _ref3.getSessionCache,
_ref3$storageKey = _ref3.storageKey,
storageKey = _ref3$storageKey === void 0 ? "HUDSessionCache" : _ref3$storageKey,
onAfterClear = _ref3.onAfterClear,
onError = _ref3.onError;
var result = {
ok: true,
reason: "ok",
preservedKeys: [],
clearedKeys: [],
cacheBefore: null,
cacheAfter: null
};
var windowAllowed = typeof window !== "undefined" && typeof window.localStorage !== "undefined";
var safeCall = function safeCall(fn) {
var fallback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : undefined;
try {
return fn();
} catch (error) {
if (typeof onError === "function") {
try {
onError(error);
} catch (_unused) {}
}
return fallback;
}
};
var readLocal = function readLocal() {
return safeCall(function () {
if (!windowAllowed) {
return {};
}
var raw = window.localStorage.getItem(storageKey);
if (!raw) {
return {};
}
try {
return JSON.parse(raw) || {};
} catch (_unused2) {
return {};
}
}, {});
};
var writeLocal = function writeLocal(obj) {
return safeCall(function () {
if (!windowAllowed) {
return;
}
if (!obj || Object.keys(obj).length === 0) {
window.localStorage.removeItem(storageKey);
return;
}
window.localStorage.setItem(storageKey, JSON.stringify(obj));
});
};
var removeLocal = function removeLocal() {
return safeCall(function () {
if (!windowAllowed) {
return;
}
window.localStorage.removeItem(storageKey);
});
};
var removeKey = function removeKey(key) {
return safeCall(function () {
if (!windowAllowed) {
return;
}
window.localStorage.removeItem(key);
});
};
var normArray = function normArray(arr) {
return Array.isArray(arr) ? Array.from(new Set(arr.filter(function (k) {
return typeof k === "string" && k.length > 0;
}))) : [];
};
var clearList = normArray(keysToClear);
var preserveList = normArray(preserveKeys);
setSignedIn(false);
setSignedUser({});
removeKey("SignedUserCredential");
removeKey("UserSignedIn");
removeKey("SignedSessionStart");
removeKey("SignedSessionExpiresAt");
removeKey("SignedSessionTimeout");
if (saveSessionCache === true) {
return result;
}
var cacheBefore = typeof getSessionCache === "function" ? safeCall(function () {
return getSessionCache();
}) || {} : readLocal();
result.cacheBefore = cacheBefore ? JSON.parse(JSON.stringify(cacheBefore)) : {};
if (clearList.length > 0) {
if (typeof clearFromSessionCache === "function") {
safeCall(function () {
return clearFromSessionCache(clearList);
});
} else {
var cache = _objectSpread({}, cacheBefore || {});
var _iterator = _createForOfIteratorHelper(clearList),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var k = _step.value;
if (k in cache) {
delete cache[k];
result.clearedKeys.push(k);
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
if (typeof updateSessionCache === "function") {
safeCall(function () {
return updateSessionCache(cache);
});
} else {
writeLocal(cache);
}
}
var _after = typeof getSessionCache === "function" ? safeCall(function () {
return getSessionCache();
}) || {} : readLocal();
result.cacheAfter = _after ? JSON.parse(JSON.stringify(_after)) : {};
result.preservedKeys = Object.keys(result.cacheAfter);
if (typeof onAfterClear === "function") {
safeCall(function () {
return onAfterClear(result);
});
}
return result;
}
var preserved = {};
for (var _i = 0, _Object$keys = Object.keys(cacheBefore || {}); _i < _Object$keys.length; _i++) {
var _k = _Object$keys[_i];
if (preserveList.includes(_k)) {
preserved[_k] = cacheBefore[_k];
result.preservedKeys.push(_k);
} else {
result.clearedKeys.push(_k);
}
}
if (typeof clearSessionCache === "function" && preserveList.length === 0) {
safeCall(function () {
return clearSessionCache();
});
} else {
if (typeof updateSessionCache === "function") {
safeCall(function () {
return updateSessionCache(preserved);
});
} else {
if (Object.keys(preserved).length === 0) {
removeLocal();
} else {
writeLocal(preserved);
}
}
}
var after = typeof getSessionCache === "function" ? safeCall(function () {
return getSessionCache();
}) || {} : readLocal();
result.cacheAfter = after ? JSON.parse(JSON.stringify(after)) : {};
if (typeof onAfterClear === "function") {
safeCall(function () {
return onAfterClear(result);
});
}
return result;
}, []);
var computeExpiryTs = useCallback(function () {
var ctx = {
signedUser: signedUser,
signedIn: signedIn,
localStorage: localStorage,
useAbsoluteExpiration: useAbsoluteExpiration,
signedSessionTimeout: signedSessionTimeout,
signedUserExpirationKey: signedUserExpirationKey
};
if (typeof getExpiryRef.current === "function") {
var ts = getExpiryRef.current(ctx);
if (typeof ts === "number" && !Number.isNaN(ts)) {
return ts;
}
}
if (signedUserExpirationKey && signedUser !== null && signedUser !== void 0 && signedUser[signedUserExpirationKey]) {
var raw = signedUser[signedUserExpirationKey];
var asNum = typeof raw === "number" ? raw : parseInt(raw, 10);
if (!Number.isNaN(asNum)) {
return asNum;
}
var asDate = new Date(raw).getTime();
if (!Number.isNaN(asDate)) {
return asDate;
}
}
if (useAbsoluteExpiration) {
var stored = parseInt(localStorage.getItem("SignedSessionExpiresAt"), 10);
if (!Number.isNaN(stored)) {
return stored;
}
} else {
var start = parseInt(localStorage.getItem("SignedSessionStart"), 10);
var timeout = parseInt(localStorage.getItem("SignedSessionTimeout"), 10) || signedSessionTimeout;
if (!Number.isNaN(start)) {
return start + timeout * 1000;
}
}
return null;
}, [signedUser, signedIn, useAbsoluteExpiration, signedSessionTimeout, signedUserExpirationKey]);
/**
* Checks if the user authentication session timed out.
*
* @function
* @name checkSignedSessionTimeout
*/
var checkSignedSessionTimeout = useCallback(function () {
var now = Date.now();
var expiresAt = computeExpiryTs();
if (expiresAt) {
var timeLeft = Math.max(0, Math.floor((expiresAt - now) / 1000));
if (timeLeft <= 0) {
signOut(saveSessionCacheOnTimeout, keysToClearOnTimeout);
if (onSessionExpire) {
onSessionExpire();
}
} else if (onSessionTimeWarning && timeLeft <= sessionWarningThreshold) {
onSessionTimeWarning(timeLeft);
}
}
}, [computeExpiryTs, signOut, saveSessionCacheOnTimeout, keysToClearOnTimeout, onSessionTimeWarning, sessionWarningThreshold, onSessionExpire]);
var shouldExtendNow = useCallback(function () {
if (!signedIn) {
return false;
}
var expiry = computeExpiryTs();
if (!expiry) {
return false;
}
return expiry - Date.now() <= sessionExtensionThreshold;
}, [signedIn, computeExpiryTs, sessionExtensionThreshold]);
var requestSessionExtend = useCallback( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
var reason,
now,
ctx,
maybeNewTs,
_args2 = arguments;
return _regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) switch (_context2.prev = _context2.next) {
case 0:
reason = _args2.length > 0 && _args2[0] !== undefined ? _args2[0] : "manual|activity";
if (sessionRenewalEnabledRef.current) {
_context2.next = 3;
break;
}
return _context2.abrupt("return");
case 3:
now = Date.now();
if (!(now - lastExtendAtRef.current < minExtendInterval)) {
_context2.next = 6;
break;
}
return _context2.abrupt("return");
case 6:
lastExtendAtRef.current = now;
if (!(typeof extendFnRef.current !== "function")) {
_context2.next = 9;
break;
}
return _context2.abrupt("return");
case 9:
ctx = {
reason: reason,
signedUser: signedUser,
signedIn: signedIn,
localStorage: localStorage,
previousExpiryTs: computeExpiryTs(),
useAbsoluteExpiration: useAbsoluteExpiration
};
_context2.prev = 10;
_context2.next = 13;
return extendFnRef.current(ctx);
case 13:
maybeNewTs = _context2.sent;
if (typeof maybeNewTs === "number" && !Number.isNaN(maybeNewTs) && useAbsoluteExpiration) {
localStorage.setItem("SignedSessionExpiresAt", String(maybeNewTs));
}
if (onSessionRenew) {
onSessionRenew(typeof maybeNewTs === "number" ? maybeNewTs : null);
}
_context2.next = 20;
break;
case 18:
_context2.prev = 18;
_context2.t0 = _context2["catch"](10);
case 20:
case "end":
return _context2.stop();
}
}, _callee2, null, [[10, 18]]);
})), [computeExpiryTs, signedUser, signedIn, useAbsoluteExpiration, minExtendInterval, onSessionRenew]);
var activityHandler = useCallback(function () {
if (shouldExtendNow()) {
requestSessionExtend("activity");
}
}, [shouldExtendNow, requestSessionExtend]);
var relativeSessionExtend = useCallback(function (_ref5) {
var useAbsoluteExpiration = _ref5.useAbsoluteExpiration,
localStorage = _ref5.localStorage;
if (useAbsoluteExpiration) {
return;
}
var now = Date.now();
var timeoutSec = parseInt(localStorage.getItem("SignedSessionTimeout"), 10) || signedSessionTimeout;
localStorage.setItem("SignedSessionStart", String(now));
return now + timeoutSec * 1000;
}, [useAbsoluteExpiration, signedSessionTimeout]);
var updateSignedUser = useCallback( /*#__PURE__*/function () {
var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee3(updater) {
var _ref7,
_ref7$persist,
persist,
_ref7$extend,
extend,
_ref7$extendReason,
extendReason,
next,
_args3 = arguments;
return _regeneratorRuntime.wrap(function _callee3$(_context3) {
while (1) switch (_context3.prev = _context3.next) {
case 0:
_ref7 = _args3.length > 1 && _args3[1] !== undefined ? _args3[1] : {}, _ref7$persist = _ref7.persist, persist = _ref7$persist === void 0 ? true : _ref7$persist, _ref7$extend = _ref7.extend, extend = _ref7$extend === void 0 ? false : _ref7$extend, _ref7$extendReason = _ref7.extendReason, extendReason = _ref7$extendReason === void 0 ? "manual|credential-update" : _ref7$extendReason;
next = typeof updater === "function" ? updater(signedUser) : updater;
setSignedUser(next);
if (!(persist && signedIn)) {
_context3.next = 6;
break;
}
_context3.next = 6;
return syncStateToCache(next, true);
case 6:
if (extend) {
requestSessionExtend(extendReason);
}
return _context3.abrupt("return", next);
case 8:
case "end":
return _context3.stop();
}
}, _callee3);
}));
return function (_x3) {
return _ref6.apply(this, arguments);
};
}(), [signedUser, signedIn, syncStateToCache, requestSessionExtend]);
var updateSignedUserProperty = useCallback( /*#__PURE__*/function () {
var _ref8 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee4(path, value, options) {
return _regeneratorRuntime.wrap(function _callee4$(_context4) {
while (1) switch (_context4.prev = _context4.next) {
case 0:
return _context4.abrupt("return", updateSignedUser(function (prev) {
return UpdateObject(prev, path, value);
}, options));
case 1:
case "end":
return _context4.stop();
}
}, _callee4);
}));
return function (_x4, _x5, _x6) {
return _ref8.apply(this, arguments);
};
}(), [updateSignedUser]);
useEffect(function () {
extendFnRef.current = extendSession || relativeSessionExtend;
}, [extendSession, relativeSessionExtend]);
useEffect(function () {
getExpiryRef.current = getExpiryTs || null;
}, [getExpiryTs]);
useEffect(function () {
if (!signedIn || useAbsoluteExpiration) {
return;
}
var timeout = parseInt(localStorage.getItem("SignedSessionTimeout"), 10);
var start = parseInt(localStorage.getItem("SignedSessionStart"), 10);
if (Number.isNaN(start) || Number.isNaN(timeout)) {
var now = Date.now();
localStorage.setItem("SignedSessionTimeout", String(signedSessionTimeout));
localStorage.setItem("SignedSessionStart", String(now));
}
}, [signedIn, useAbsoluteExpiration, signedSessionTimeout]);
useEffect(function () {
if (!autoExtendOnActivity) {
return;
}
var events = ["mousemove", "keydown", "click", "scroll"];
events.forEach(function (e) {
return window.addEventListener(e, activityHandler);
});
return function () {
return events.forEach(function (e) {
return window.removeEventListener(e, activityHandler);
});
};
}, [autoExtendOnActivity, activityHandler]);
useEffect(function () {
if (!autoSignIn) {
return;
}
var _currentSignedState = currentSignedState(),
currentSignedUser = _currentSignedState.currentSignedUser,
currentSignedIn = _currentSignedState.currentSignedIn;
_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee5() {
var parsed;
return _regeneratorRuntime.wrap(function _callee5$(_context5) {
while (1) switch (_context5.prev = _context5.next) {
case 0:
_context5.prev = 0;
if (!encryptAuthIdentity) {
_context5.next = 7;
break;
}
_context5.next = 4;
return decryptData(currentSignedUser, resolvedSeed, resolvedOffset, identityDepth);
case 4:
_context5.t0 = _context5.sent;
_context5.next = 8;
break;
case 7:
_context5.t0 = JSON.parse(currentSignedUser);
case 8:
parsed = _context5.t0;
if (parsed && _typeof(parsed) === "object") {
setSignedUser(parsed);
setSignedIn(currentSignedIn);
sessionInitialized.current = true;
}
_context5.next = 17;
break;
case 12:
_context5.prev = 12;
_context5.t1 = _context5["catch"](0);
setSignedUser({});
setSignedIn(false);
sessionInitialized.current = false;
case 17:
case "end":
return _context5.stop();
}
}, _callee5, null, [[0, 12]]);
}))();
}, [autoSignIn, encryptAuthIdentity, resolvedSeed, resolvedOffset, identityDepth]);
useEffect(function () {
if (sessionInitialized.current) {
return;
}
if (signedIn && signedUser && Object.keys(signedUser).length > 0) {
syncStateToCache(signedUser, true);
}
}, [signedIn, signedUser, syncStateToCache]);
useEffect(function () {
checkSignedSessionTimeout();
var interval = setInterval(checkSignedSessionTimeout, sessionCheckInterval);
return function () {
return clearInterval(interval);
};
}, [signedIn, checkSignedSessionTimeout, sessionCheckInterval]);
return /*#__PURE__*/React.createElement(AuthContext.Provider, {
value: {
setAutoExtendSessionOnActivity: function setAutoExtendSessionOnActivity(v) {
setAutoExtendOnActivity(!!v);
},
setGetSessionExpiry: function setGetSessionExpiry(fn) {
getExpiryRef.current = fn;
},
setExtendSession: function setExtendSession(fn) {
extendFnRef.current = fn;
},
setSessionRenewal: function setSessionRenewal() {
var enabled = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
sessionRenewalEnabledRef.current = !!enabled;
},
requestSessionExtend: requestSessionExtend,
updateSignedUserProperty: updateSignedUserProperty,
updateSignedUser: updateSignedUser,
signedUser: signedUser,
setSignedUser: setSignedUser,
signedIn: signedIn,
signIn: signIn,
signOut: signOut
}
}, children);
};
/**
* Allows access to the signed user's credentials and provides functions to checking the user's authentication state to signing a user out.
* This component allows access to signedUser, setSignedUser, signedIn, signIn, signOut.
*
* @hook
* @returns {Object} The authentication context including user state and auth functions.
* @example
* const { signedUser, signedIn, signIn, signOut } = useAuth();
*/
export var useAuth = function useAuth() {
var context = useContext(AuthContext);
if (!context) {
throw new Error("Must use within an AuthProvider");
}
return context;
};
/**
* useAuthSessionMonitor provides real-time monitoring of the current session.
*
* @hook
* @param {Object} options
* @param {number} [sessionTimeout] - Override session timeout in seconds. If not provided, uses AuthProvider fallback.
* @param {boolean} [useAbsoluteExpiration=false] - Whether to use localStorage "SignedSessionExpiresAt".
* @param {string|null} [signedUserExpirationKey=null] - Key from signedUser object for expiration.
* @param {function} [onExpire] - Called once when session expires.
* @param {function} [onTimeUpdate] - Called on each timeLeft update.
* @param {function} [onWarning] - Called once when timeLeft drops below threshold.
* @param {number} [warningThreshold=300] - Seconds before expiration to trigger onWarning.
* @returns {{ timeLeft: number, expiresAt: number|null, expired: boolean }}
*/
export function useAuthSessionMonitor() {
var _ref10 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
sessionTimeout = _ref10.sessionTimeout,
_ref10$useAbsoluteExp = _ref10.useAbsoluteExpiration,
useAbsoluteExpiration = _ref10$useAbsoluteExp === void 0 ? false : _ref10$useAbsoluteExp,
_ref10$signedUserExpi = _ref10.signedUserExpirationKey,
signedUserExpirationKey = _ref10$signedUserExpi === void 0 ? null : _ref10$signedUserExpi,
onExpire = _ref10.onExpire,
onTimeUpdate = _ref10.onTimeUpdate,
onWarning = _ref10.onWarning,
_ref10$warningThresho = _ref10.warningThreshold,
warningThreshold = _ref10$warningThresho === void 0 ? 300 : _ref10$warningThresho;
var _useAuth = useAuth(),
signedUser = _useAuth.signedUser,
signedIn = _useAuth.signedIn;
var _useState7 = useState(null),
_useState8 = _slicedToArray(_useState7, 2),
timeLeft = _useState8[0],
setTimeLeft = _useState8[1];
var _useState9 = useState(null),
_useState10 = _slicedToArray(_useState9, 2),
expiresAt = _useState10[0],
setExpiresAt = _useState10[1];
var _useState11 = useState(false),
_useState12 = _slicedToArray(_useState11, 2),
warned = _useState12[0],
setWarned = _useState12[1];
var _useState13 = useState(false),
_useState14 = _slicedToArray(_useState13, 2),
expired = _useState14[0],
setExpired = _useState14[1];
useEffect(function () {
var interval = setInterval(function () {
if (!signedIn) {
setTimeLeft(null);
setExpiresAt(null);
setWarned(false);
setExpired(false);
return;
}
var now = Date.now();
var resolvedExpiresAt = null;
if (signedUserExpirationKey && signedUser !== null && signedUser !== void 0 && signedUser[signedUserExpirationKey]) {
resolvedExpiresAt = parseInt(signedUser[signedUserExpirationKey], 10);
} else if (useAbsoluteExpiration) {
var stored = localStorage.getItem("SignedSessionExpiresAt");
if (stored) {
resolvedExpiresAt = parseInt(stored, 10);
}
} else {
var _ref11;
var start = parseInt(localStorage.getItem("SignedSessionStart"), 10);
var timeout = (_ref11 = sessionTimeout !== null && sessionTimeout !== void 0 ? sessionTimeout : parseInt(localStorage.getItem("SignedSessionTimeout"), 10)) !== null && _ref11 !== void 0 ? _ref11 : 18000;
if (!isNaN(start)) {
resolvedExpiresAt = start + timeout * 1000;
}
}
if (resolvedExpiresAt) {
var left = Math.max(0, Math.floor((resolvedExpiresAt - now) / 1000));
setTimeLeft(left);
setExpiresAt(resolvedExpiresAt);
if (typeof onTimeUpdate === "function") {
onTimeUpdate(left);
}
if (left <= 0 && !expired) {
setExpired(true);
if (typeof onExpire === "function") {
onExpire();
}
}
if (left <= warningThreshold && !warned) {
setWarned(true);
if (typeof onWarning === "function") {
onWarning(left);
}
}
if (left > warningThreshold) {
setWarned(false);
}
} else {
setTimeLeft(null);
setExpiresAt(null);
}
}, 1000);
return function () {
return clearInterval(interval);
};
}, [signedUser, signedIn, sessionTimeout, signedUserExpirationKey, useAbsoluteExpiration, onExpire, onTimeUpdate, onWarning, warningThreshold, warned, expired]);
return {
timeLeft: timeLeft,
expiresAt: expiresAt,
expired: typeof timeLeft === "number" ? timeLeft <= 0 : false
};
}
;