UNPKG

payload

Version:

Node, React and MongoDB Headless CMS and Application Framework

359 lines (358 loc) • 34.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: all[name] }); } _export(exports, { AuthProvider: function() { return AuthProvider; }, useAuth: function() { return useAuth; } }); const _modal = require("@faceless-ui/modal"); const _qs = /*#__PURE__*/ _interop_require_default(require("qs")); const _react = /*#__PURE__*/ _interop_require_wildcard(require("react")); const _reacti18next = require("react-i18next"); const _reactrouterdom = require("react-router-dom"); const _reacttoastify = require("react-toastify"); const _api = require("../../../api"); const _useDebounce = /*#__PURE__*/ _interop_require_default(require("../../../hooks/useDebounce")); const _Config = require("../Config"); const _Locale = require("../Locale"); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interop_require_wildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = { __proto__: null }; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for(var key in obj){ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } const Context = /*#__PURE__*/ (0, _react.createContext)({}); const maxTimeoutTime = 2147483647; const AuthProvider = ({ children })=>{ const [user, setUser] = (0, _react.useState)(); const [tokenInMemory, setTokenInMemory] = (0, _react.useState)(); const [tokenExpiration, setTokenExpiration] = (0, _react.useState)(); const { pathname } = (0, _reactrouterdom.useLocation)(); const { push } = (0, _reactrouterdom.useHistory)(); const { code } = (0, _Locale.useLocale)(); const config = (0, _Config.useConfig)(); const { admin: { autoLogin, inactivityRoute: logoutInactivityRoute, user: userSlug }, routes: { admin, api }, serverURL } = config; const [permissions, setPermissions] = (0, _react.useState)(); const { i18n } = (0, _reacti18next.useTranslation)(); const { closeAllModals, openModal } = (0, _modal.useModal)(); const [lastLocationChange, setLastLocationChange] = (0, _react.useState)(0); const debouncedLocationChange = (0, _useDebounce.default)(lastLocationChange, 10000); const id = user?.id; const redirectToInactivityRoute = (0, _react.useCallback)(()=>{ if (window.location.pathname.startsWith(admin)) { const redirectParam = `?redirect=${encodeURIComponent(window.location.pathname.replace(admin, ''))}`; push(`${admin}${logoutInactivityRoute}${redirectParam}`); } else { push(`${admin}${logoutInactivityRoute}`); } closeAllModals(); }, [ push, admin, logoutInactivityRoute, closeAllModals ]); const revokeTokenAndExpire = (0, _react.useCallback)(()=>{ setTokenInMemory(undefined); setTokenExpiration(undefined); }, []); const setTokenAndExpiration = (0, _react.useCallback)((json)=>{ const token = json?.token || json?.refreshedToken; if (token && json?.exp) { setTokenInMemory(token); setTokenExpiration(json.exp); } else { revokeTokenAndExpire(); } }, [ revokeTokenAndExpire ]); const refreshCookie = (0, _react.useCallback)((forceRefresh)=>{ const now = Math.round(new Date().getTime() / 1000); const remainingTime = (typeof tokenExpiration === 'number' ? tokenExpiration : 0) - now; if (forceRefresh || tokenExpiration && remainingTime < 120) { setTimeout(async ()=>{ try { const request = await _api.requests.post(`${serverURL}${api}/${userSlug}/refresh-token`, { headers: { 'Accept-Language': i18n.language } }); if (request.status === 200) { const json = await request.json(); setUser(json.user); setTokenAndExpiration(json); } else { setUser(null); redirectToInactivityRoute(); } } catch (e) { _reacttoastify.toast.error(e.message); } }, 1000); } }, [ tokenExpiration, serverURL, api, userSlug, i18n, redirectToInactivityRoute, setTokenAndExpiration ]); const refreshCookieAsync = (0, _react.useCallback)(async (skipSetUser)=>{ try { const request = await _api.requests.post(`${serverURL}${api}/${userSlug}/refresh-token`, { headers: { 'Accept-Language': i18n.language } }); if (request.status === 200) { const json = await request.json(); if (!skipSetUser) { setUser(json.user); setTokenAndExpiration(json); } return json.user; } setUser(null); redirectToInactivityRoute(); return null; } catch (e) { _reacttoastify.toast.error(`Refreshing token failed: ${e.message}`); return null; } }, [ serverURL, api, userSlug, i18n, redirectToInactivityRoute, setTokenAndExpiration ]); const logOut = (0, _react.useCallback)(()=>{ setUser(null); revokeTokenAndExpire(); _api.requests.post(`${serverURL}${api}/${userSlug}/logout`); }, [ serverURL, api, userSlug, revokeTokenAndExpire ]); const refreshPermissions = (0, _react.useCallback)(async ()=>{ const params = { locale: code }; try { const request = await _api.requests.get(`${serverURL}${api}/access?${_qs.default.stringify(params)}`, { headers: { 'Accept-Language': i18n.language } }); if (request.status === 200) { const json = await request.json(); setPermissions(json); } else { throw new Error(`Fetching permissions failed with status code ${request.status}`); } } catch (e) { _reacttoastify.toast.error(`Refreshing permissions failed: ${e.message}`); } }, [ serverURL, api, i18n, code ]); const fetchFullUser = _react.default.useCallback(async ()=>{ try { const request = await _api.requests.get(`${serverURL}${api}/${userSlug}/me`, { headers: { 'Accept-Language': i18n.language } }); if (request.status === 200) { const json = await request.json(); if (json?.user) { setUser(json.user); if (json?.token) { setTokenAndExpiration(json); } } else if (autoLogin && autoLogin.prefillOnly !== true) { // auto log-in with the provided autoLogin credentials. This is used in dev mode // so you don't have to log in over and over again const autoLoginResult = await _api.requests.post(`${serverURL}${api}/${userSlug}/login`, { body: JSON.stringify({ email: autoLogin.email, password: autoLogin.password }), headers: { 'Accept-Language': i18n.language, 'Content-Type': 'application/json' } }); if (autoLoginResult.status === 200) { const autoLoginJson = await autoLoginResult.json(); setUser(autoLoginJson.user); if (autoLoginJson?.token) { setTokenAndExpiration(autoLoginJson); } } else { setUser(null); revokeTokenAndExpire(); } } else { setUser(null); revokeTokenAndExpire(); } } } catch (e) { _reacttoastify.toast.error(`Fetching user failed: ${e.message}`); } }, [ serverURL, api, userSlug, i18n, autoLogin, setTokenAndExpiration, revokeTokenAndExpire ]); // On mount, get user and set (0, _react.useEffect)(()=>{ fetchFullUser(); }, [ fetchFullUser ]); // When location changes, refresh cookie (0, _react.useEffect)(()=>{ if (id) { refreshCookie(); } }, [ debouncedLocationChange, refreshCookie, id ]); (0, _react.useEffect)(()=>{ setLastLocationChange(Date.now()); }, [ pathname ]); // When user changes, get new access (0, _react.useEffect)(()=>{ if (id) { refreshPermissions(); } }, [ i18n, id, api, serverURL, refreshPermissions ]); (0, _react.useEffect)(()=>{ let reminder; const now = Math.round(new Date().getTime() / 1000); const remainingTime = typeof tokenExpiration === 'number' ? tokenExpiration - now : 0; if (remainingTime > 0) { reminder = setTimeout(()=>{ openModal('stay-logged-in'); }, Math.max(Math.min((remainingTime - 60) * 1000, maxTimeoutTime))); } return ()=>{ if (reminder) clearTimeout(reminder); }; }, [ tokenExpiration, openModal ]); (0, _react.useEffect)(()=>{ let forceLogOut; const now = Math.round(new Date().getTime() / 1000); const remainingTime = typeof tokenExpiration === 'number' ? tokenExpiration - now : 0; if (remainingTime > 0) { forceLogOut = setTimeout(()=>{ setUser(null); revokeTokenAndExpire(); redirectToInactivityRoute(); }, Math.max(Math.min(remainingTime * 1000, maxTimeoutTime), 0)); } return ()=>{ if (forceLogOut) clearTimeout(forceLogOut); }; }, [ tokenExpiration, closeAllModals, i18n, redirectToInactivityRoute, revokeTokenAndExpire ]); return /*#__PURE__*/ _react.default.createElement(Context.Provider, { value: { fetchFullUser, logOut, permissions, refreshCookie, refreshCookieAsync, refreshPermissions, setUser, token: tokenInMemory, user } }, children); }; const useAuth = ()=>(0, _react.useContext)(Context); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hZG1pbi9jb21wb25lbnRzL3V0aWxpdGllcy9BdXRoL2luZGV4LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1c2VNb2RhbCB9IGZyb20gJ0BmYWNlbGVzcy11aS9tb2RhbCdcbmltcG9ydCBxcyBmcm9tICdxcydcbmltcG9ydCBSZWFjdCwgeyBjcmVhdGVDb250ZXh0LCB1c2VDYWxsYmFjaywgdXNlQ29udGV4dCwgdXNlRWZmZWN0LCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgdXNlVHJhbnNsYXRpb24gfSBmcm9tICdyZWFjdC1pMThuZXh0J1xuaW1wb3J0IHsgdXNlSGlzdG9yeSwgdXNlTG9jYXRpb24gfSBmcm9tICdyZWFjdC1yb3V0ZXItZG9tJ1xuaW1wb3J0IHsgdG9hc3QgfSBmcm9tICdyZWFjdC10b2FzdGlmeSdcblxuaW1wb3J0IHR5cGUgeyBQZXJtaXNzaW9ucywgVXNlciB9IGZyb20gJy4uLy4uLy4uLy4uL2F1dGgvdHlwZXMnXG5pbXBvcnQgdHlwZSB7IEF1dGhDb250ZXh0IH0gZnJvbSAnLi90eXBlcydcblxuaW1wb3J0IHsgcmVxdWVzdHMgfSBmcm9tICcuLi8uLi8uLi9hcGknXG5pbXBvcnQgdXNlRGVib3VuY2UgZnJvbSAnLi4vLi4vLi4vaG9va3MvdXNlRGVib3VuY2UnXG5pbXBvcnQgeyB1c2VDb25maWcgfSBmcm9tICcuLi9Db25maWcnXG5pbXBvcnQgeyB1c2VMb2NhbGUgfSBmcm9tICcuLi9Mb2NhbGUnXG5cbmNvbnN0IENvbnRleHQgPSBjcmVhdGVDb250ZXh0KHt9IGFzIEF1dGhDb250ZXh0KVxuXG5jb25zdCBtYXhUaW1lb3V0VGltZSA9IDIxNDc0ODM2NDdcblxuZXhwb3J0IGNvbnN0IEF1dGhQcm92aWRlcjogUmVhY3QuRkM8eyBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlIH0+ID0gKHsgY2hpbGRyZW4gfSkgPT4ge1xuICBjb25zdCBbdXNlciwgc2V0VXNlcl0gPSB1c2VTdGF0ZTxVc2VyIHwgbnVsbD4oKVxuICBjb25zdCBbdG9rZW5Jbk1lbW9yeSwgc2V0VG9rZW5Jbk1lbW9yeV0gPSB1c2VTdGF0ZTxzdHJpbmc+KClcbiAgY29uc3QgW3Rva2VuRXhwaXJhdGlvbiwgc2V0VG9rZW5FeHBpcmF0aW9uXSA9IHVzZVN0YXRlPG51bWJlcj4oKVxuICBjb25zdCB7IHBhdGhuYW1lIH0gPSB1c2VMb2NhdGlvbigpXG4gIGNvbnN0IHsgcHVzaCB9ID0gdXNlSGlzdG9yeSgpXG4gIGNvbnN0IHsgY29kZSB9ID0gdXNlTG9jYWxlKClcblxuICBjb25zdCBjb25maWcgPSB1c2VDb25maWcoKVxuXG4gIGNvbnN0IHtcbiAgICBhZG1pbjogeyBhdXRvTG9naW4sIGluYWN0aXZpdHlSb3V0ZTogbG9nb3V0SW5hY3Rpdml0eVJvdXRlLCB1c2VyOiB1c2VyU2x1ZyB9LFxuICAgIHJvdXRlczogeyBhZG1pbiwgYXBpIH0sXG4gICAgc2VydmVyVVJMLFxuICB9ID0gY29uZmlnXG5cbiAgY29uc3QgW3Blcm1pc3Npb25zLCBzZXRQZXJtaXNzaW9uc10gPSB1c2VTdGF0ZTxQZXJtaXNzaW9ucz4oKVxuXG4gIGNvbnN0IHsgaTE4biB9ID0gdXNlVHJhbnNsYXRpb24oKVxuICBjb25zdCB7IGNsb3NlQWxsTW9kYWxzLCBvcGVuTW9kYWwgfSA9IHVzZU1vZGFsKClcbiAgY29uc3QgW2xhc3RMb2NhdGlvbkNoYW5nZSwgc2V0TGFzdExvY2F0aW9uQ2hhbmdlXSA9IHVzZVN0YXRlKDApXG4gIGNvbnN0IGRlYm91bmNlZExvY2F0aW9uQ2hhbmdlID0gdXNlRGVib3VuY2UobGFzdExvY2F0aW9uQ2hhbmdlLCAxMDAwMClcblxuICBjb25zdCBpZCA9IHVzZXI/LmlkXG5cbiAgY29uc3QgcmVkaXJlY3RUb0luYWN0aXZpdHlSb3V0ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBpZiAod2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLnN0YXJ0c1dpdGgoYWRtaW4pKSB7XG4gICAgICBjb25zdCByZWRpcmVjdFBhcmFtID0gYD9yZWRpcmVjdD0ke2VuY29kZVVSSUNvbXBvbmVudChcbiAgICAgICAgd2luZG93LmxvY2F0aW9uLnBhdGhuYW1lLnJlcGxhY2UoYWRtaW4sICcnKSxcbiAgICAgICl9YFxuICAgICAgcHVzaChgJHthZG1pbn0ke2xvZ291dEluYWN0aXZpdHlSb3V0ZX0ke3JlZGlyZWN0UGFyYW19YClcbiAgICB9IGVsc2Uge1xuICAgICAgcHVzaChgJHthZG1pbn0ke2xvZ291dEluYWN0aXZpdHlSb3V0ZX1gKVxuICAgIH1cbiAgICBjbG9zZUFsbE1vZGFscygpXG4gIH0sIFtwdXNoLCBhZG1pbiwgbG9nb3V0SW5hY3Rpdml0eVJvdXRlLCBjbG9zZUFsbE1vZGFsc10pXG5cbiAgY29uc3QgcmV2b2tlVG9rZW5BbmRFeHBpcmUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0VG9rZW5Jbk1lbW9yeSh1bmRlZmluZWQpXG4gICAgc2V0VG9rZW5FeHBpcmF0aW9uKHVuZGVmaW5lZClcbiAgfSwgW10pXG5cbiAgY29uc3Qgc2V0VG9rZW5BbmRFeHBpcmF0aW9uID0gdXNlQ2FsbGJhY2soXG4gICAgKGpzb24pID0+IHtcbiAgICAgIGNvbnN0IHRva2VuID0ganNvbj8udG9rZW4gfHwganNvbj8ucmVmcmVzaGVkVG9rZW5cbiAgICAgIGlmICh0b2tlbiAmJiBqc29uPy5leHApIHtcbiAgICAgICAgc2V0VG9rZW5Jbk1lbW9yeSh0b2tlbilcbiAgICAgICAgc2V0VG9rZW5FeHBpcmF0aW9uKGpzb24uZXhwKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV2b2tlVG9rZW5BbmRFeHBpcmUoKVxuICAgICAgfVxuICAgIH0sXG4gICAgW3Jldm9rZVRva2VuQW5kRXhwaXJlXSxcbiAgKVxuXG4gIGNvbnN0IHJlZnJlc2hDb29raWUgPSB1c2VDYWxsYmFjayhcbiAgICAoZm9yY2VSZWZyZXNoPzogYm9vbGVhbikgPT4ge1xuICAgICAgY29uc3Qgbm93ID0gTWF0aC5yb3VuZChuZXcgRGF0ZSgpLmdldFRpbWUoKSAvIDEwMDApXG4gICAgICBjb25zdCByZW1haW5pbmdUaW1lID0gKHR5cGVvZiB0b2tlbkV4cGlyYXRpb24gPT09ICdudW1iZXInID8gdG9rZW5FeHBpcmF0aW9uIDogMCkgLSBub3dcblxuICAgICAgaWYgKGZvcmNlUmVmcmVzaCB8fCAodG9rZW5FeHBpcmF0aW9uICYmIHJlbWFpbmluZ1RpbWUgPCAxMjApKSB7XG4gICAgICAgIHNldFRpbWVvdXQoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICBjb25zdCByZXF1ZXN0ID0gYXdhaXQgcmVxdWVzdHMucG9zdChgJHtzZXJ2ZXJVUkx9JHthcGl9LyR7dXNlclNsdWd9L3JlZnJlc2gtdG9rZW5gLCB7XG4gICAgICAgICAgICAgIGhlYWRlcnM6IHtcbiAgICAgICAgICAgICAgICAnQWNjZXB0LUxhbmd1YWdlJzogaTE4bi5sYW5ndWFnZSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pXG5cbiAgICAgICAgICAgIGlmIChyZXF1ZXN0LnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICAgIGNvbnN0IGpzb24gPSBhd2FpdCByZXF1ZXN0Lmpzb24oKVxuICAgICAgICAgICAgICBzZXRVc2VyKGpzb24udXNlcilcbiAgICAgICAgICAgICAgc2V0VG9rZW5BbmRFeHBpcmF0aW9uKGpzb24pXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBzZXRVc2VyKG51bGwpXG4gICAgICAgICAgICAgIHJlZGlyZWN0VG9JbmFjdGl2aXR5Um91dGUoKVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRvYXN0LmVycm9yKGUubWVzc2FnZSlcbiAgICAgICAgICB9XG4gICAgICAgIH0sIDEwMDApXG4gICAgICB9XG4gICAgfSxcbiAgICBbXG4gICAgICB0b2tlbkV4cGlyYXRpb24sXG4gICAgICBzZXJ2ZXJVUkwsXG4gICAgICBhcGksXG4gICAgICB1c2VyU2x1ZyxcbiAgICAgIGkxOG4sXG4gICAgICByZWRpcmVjdFRvSW5hY3Rpdml0eVJvdXRlLFxuICAgICAgc2V0VG9rZW5BbmRFeHBpcmF0aW9uLFxuICAgIF0sXG4gIClcblxuICBjb25zdCByZWZyZXNoQ29va2llQXN5bmMgPSB1c2VDYWxsYmFjayhcbiAgICBhc3luYyAoc2tpcFNldFVzZXI/OiBib29sZWFuKTogUHJvbWlzZTxVc2VyPiA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXF1ZXN0ID0gYXdhaXQgcmVxdWVzdHMucG9zdChgJHtzZXJ2ZXJVUkx9JHthcGl9LyR7dXNlclNsdWd9L3JlZnJlc2gtdG9rZW5gLCB7XG4gICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgJ0FjY2VwdC1MYW5ndWFnZSc6IGkxOG4ubGFuZ3VhZ2UsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAocmVxdWVzdC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICAgIGNvbnN0IGpzb24gPSBhd2FpdCByZXF1ZXN0Lmpzb24oKVxuICAgICAgICAgIGlmICghc2tpcFNldFVzZXIpIHtcbiAgICAgICAgICAgIHNldFVzZXIoanNvbi51c2VyKVxuICAgICAgICAgICAgc2V0VG9rZW5BbmRFeHBpcmF0aW9uKGpzb24pXG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBqc29uLnVzZXJcbiAgICAgICAgfVxuXG4gICAgICAgIHNldFVzZXIobnVsbClcbiAgICAgICAgcmVkaXJlY3RUb0luYWN0aXZpdHlSb3V0ZSgpXG4gICAgICAgIHJldHVybiBudWxsXG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIHRvYXN0LmVycm9yKGBSZWZyZXNoaW5nIHRva2VuIGZhaWxlZDogJHtlLm1lc3NhZ2V9YClcbiAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgIH1cbiAgICB9LFxuICAgIFtzZXJ2ZXJVUkwsIGFwaSwgdXNlclNsdWcsIGkxOG4sIHJlZGlyZWN0VG9JbmFjdGl2aXR5Um91dGUsIHNldFRva2VuQW5kRXhwaXJhdGlvbl0sXG4gIClcblxuICBjb25zdCBsb2dPdXQgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0VXNlcihudWxsKVxuICAgIHJldm9rZVRva2VuQW5kRXhwaXJlKClcbiAgICByZXF1ZXN0cy5wb3N0KGAke3NlcnZlclVSTH0ke2FwaX0vJHt1c2VyU2x1Z30vbG9nb3V0YClcbiAgfSwgW3NlcnZlclVSTCwgYXBpLCB1c2VyU2x1ZywgcmV2b2tlVG9rZW5BbmRFeHBpcmVdKVxuXG4gIGNvbnN0IHJlZnJlc2hQZXJtaXNzaW9ucyA9IHVzZUNhbGxiYWNrKGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBwYXJhbXMgPSB7XG4gICAgICBsb2NhbGU6IGNvZGUsXG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByZXF1ZXN0ID0gYXdhaXQgcmVxdWVzdHMuZ2V0KGAke3NlcnZlclVSTH0ke2FwaX0vYWNjZXNzPyR7cXMuc3RyaW5naWZ5KHBhcmFtcyl9YCwge1xuICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgJ0FjY2VwdC1MYW5ndWFnZSc6IGkxOG4ubGFuZ3VhZ2UsXG4gICAgICAgIH0sXG4gICAgICB9KVxuXG4gICAgICBpZiAocmVxdWVzdC5zdGF0dXMgPT09IDIwMCkge1xuICAgICAgICBjb25zdCBqc29uOiBQZXJtaXNzaW9ucyA9IGF3YWl0IHJlcXVlc3QuanNvbigpXG4gICAgICAgIHNldFBlcm1pc3Npb25zKGpzb24pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEZldGNoaW5nIHBlcm1pc3Npb25zIGZhaWxlZCB3aXRoIHN0YXR1cyBjb2RlICR7cmVxdWVzdC5zdGF0dXN9YClcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICB0b2FzdC5lcnJvcihgUmVmcmVzaGluZyBwZXJtaXNzaW9ucyBmYWlsZWQ6ICR7ZS5tZXNzYWdlfWApXG4gICAgfVxuICB9LCBbc2VydmVyVVJMLCBhcGksIGkxOG4sIGNvZGVdKVxuXG4gIGNvbnN0IGZldGNoRnVsbFVzZXIgPSBSZWFjdC51c2VDYWxsYmFjayhhc3luYyAoKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcXVlc3QgPSBhd2FpdCByZXF1ZXN0cy5nZXQoYCR7c2VydmVyVVJMfSR7YXBpfS8ke3VzZXJTbHVnfS9tZWAsIHtcbiAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICdBY2NlcHQtTGFuZ3VhZ2UnOiBpMThuLmxhbmd1YWdlLFxuICAgICAgICB9LFxuICAgICAgfSlcblxuICAgICAgaWYgKHJlcXVlc3Quc3RhdHVzID09PSAyMDApIHtcbiAgICAgICAgY29uc3QganNvbiA9IGF3YWl0IHJlcXVlc3QuanNvbigpXG5cbiAgICAgICAgaWYgKGpzb24/LnVzZXIpIHtcbiAgICAgICAgICBzZXRVc2VyKGpzb24udXNlcilcbiAgICAgICAgICBpZiAoanNvbj8udG9rZW4pIHtcbiAgICAgICAgICAgIHNldFRva2VuQW5kRXhwaXJhdGlvbihqc29uKVxuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmIChhdXRvTG9naW4gJiYgYXV0b0xvZ2luLnByZWZpbGxPbmx5ICE9PSB0cnVlKSB7XG4gICAgICAgICAgLy8gYXV0byBsb2ctaW4gd2l0aCB0aGUgcHJvdmlkZWQgYXV0b0xvZ2luIGNyZWRlbnRpYWxzLiBUaGlzIGlzIHVzZWQgaW4gZGV2IG1vZGVcbiAgICAgICAgICAvLyBzbyB5b3UgZG9uJ3QgaGF2ZSB0byBsb2cgaW4gb3ZlciBhbmQgb3ZlciBhZ2FpblxuICAgICAgICAgIGNvbnN0IGF1dG9Mb2dpblJlc3VsdCA9IGF3YWl0IHJlcXVlc3RzLnBvc3QoYCR7c2VydmVyVVJMfSR7YXBpfS8ke3VzZXJTbHVnfS9sb2dpbmAsIHtcbiAgICAgICAgICAgIGJvZHk6IEpTT04uc3RyaW5naWZ5KHtcbiAgICAgICAgICAgICAgZW1haWw6IGF1dG9Mb2dpbi5lbWFpbCxcbiAgICAgICAgICAgICAgcGFzc3dvcmQ6IGF1dG9Mb2dpbi5wYXNzd29yZCxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgaGVhZGVyczoge1xuICAgICAgICAgICAgICAnQWNjZXB0LUxhbmd1YWdlJzogaTE4bi5sYW5ndWFnZSxcbiAgICAgICAgICAgICAgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSlcbiAgICAgICAgICBpZiAoYXV0b0xvZ2luUmVzdWx0LnN0YXR1cyA9PT0gMjAwKSB7XG4gICAgICAgICAgICBjb25zdCBhdXRvTG9naW5Kc29uID0gYXdhaXQgYXV0b0xvZ2luUmVzdWx0Lmpzb24oKVxuICAgICAgICAgICAgc2V0VXNlcihhdXRvTG9naW5Kc29uLnVzZXIpXG4gICAgICAgICAgICBpZiAoYXV0b0xvZ2luSnNvbj8udG9rZW4pIHtcbiAgICAgICAgICAgICAgc2V0VG9rZW5BbmRFeHBpcmF0aW9uKGF1dG9Mb2dpbkpzb24pXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldFVzZXIobnVsbClcbiAgICAgICAgICAgIHJldm9rZVRva2VuQW5kRXhwaXJlKClcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2V0VXNlcihudWxsKVxuICAgICAgICAgIHJldm9rZVRva2VuQW5kRXhwaXJlKClcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRvYXN0LmVycm9yKGBGZXRjaGluZyB1c2VyIGZhaWxlZDogJHtlLm1lc3NhZ2V9YClcbiAgICB9XG4gIH0sIFtzZXJ2ZXJVUkwsIGFwaSwgdXNlclNsdWcsIGkxOG4sIGF1dG9Mb2dpbiwgc2V0VG9rZW5BbmRFeHBpcmF0aW9uLCByZXZva2VUb2tlbkFuZEV4cGlyZV0pXG5cbiAgLy8gT24gbW91bnQsIGdldCB1c2VyIGFuZCBzZXRcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBmZXRjaEZ1bGxVc2VyKClcbiAgfSwgW2ZldGNoRnVsbFVzZXJdKVxuXG4gIC8vIFdoZW4gbG9jYXRpb24gY2hhbmdlcywgcmVmcmVzaCBjb29raWVcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaWQpIHtcbiAgICAgIHJlZnJlc2hDb29raWUoKVxuICAgIH1cbiAgfSwgW2RlYm91bmNlZExvY2F0aW9uQ2hhbmdlLCByZWZyZXNoQ29va2llLCBpZF0pXG5cbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBzZXRMYXN0TG9jYXRpb25DaGFuZ2UoRGF0ZS5ub3coKSlcbiAgfSwgW3BhdGhuYW1lXSlcblxuICAvLyBXaGVuIHVzZXIgY2hhbmdlcywgZ2V0IG5ldyBhY2Nlc3NcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoaWQpIHtcbiAgICAgIHJlZnJlc2hQZXJtaXNzaW9ucygpXG4gICAgfVxuICB9LCBbaTE4biwgaWQsIGFwaSwgc2VydmVyVVJMLCByZWZyZXNoUGVybWlzc2lvbnNdKVxuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgbGV0IHJlbWluZGVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PlxuICAgIGNvbnN0IG5vdyA9IE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKVxuICAgIGNvbnN0IHJlbWFpbmluZ1RpbWUgPSB0eXBlb2YgdG9rZW5FeHBpcmF0aW9uID09PSAnbnVtYmVyJyA/IHRva2VuRXhwaXJhdGlvbiAtIG5vdyA6IDBcblxuICAgIGlmIChyZW1haW5pbmdUaW1lID4gMCkge1xuICAgICAgcmVtaW5kZXIgPSBzZXRUaW1lb3V0KFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgb3Blbk1vZGFsKCdzdGF5LWxvZ2dlZC1pbicpXG4gICAgICAgIH0sXG4gICAgICAgIE1hdGgubWF4KE1hdGgubWluKChyZW1haW5pbmdUaW1lIC0gNjApICogMTAwMCwgbWF4VGltZW91dFRpbWUpKSxcbiAgICAgIClcbiAgICB9XG5cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKHJlbWluZGVyKSBjbGVhclRpbWVvdXQocmVtaW5kZXIpXG4gICAgfVxuICB9LCBbdG9rZW5FeHBpcmF0aW9uLCBvcGVuTW9kYWxdKVxuXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgbGV0IGZvcmNlTG9nT3V0OiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PlxuICAgIGNvbnN0IG5vdyA9IE1hdGgucm91bmQobmV3IERhdGUoKS5nZXRUaW1lKCkgLyAxMDAwKVxuICAgIGNvbnN0IHJlbWFpbmluZ1RpbWUgPSB0eXBlb2YgdG9rZW5FeHBpcmF0aW9uID09PSAnbnVtYmVyJyA/IHRva2VuRXhwaXJhdGlvbiAtIG5vdyA6IDBcblxuICAgIGlmIChyZW1haW5pbmdUaW1lID4gMCkge1xuICAgICAgZm9yY2VMb2dPdXQgPSBzZXRUaW1lb3V0KFxuICAgICAgICAoKSA9PiB7XG4gICAgICAgICAgc2V0VXNlcihudWxsKVxuICAgICAgICAgIHJldm9rZVRva2VuQW5kRXhwaXJlKClcbiAgICAgICAgICByZWRpcmVjdFRvSW5hY3Rpdml0eVJvdXRlKClcbiAgICAgICAgfSxcbiAgICAgICAgTWF0aC5tYXgoTWF0aC5taW4ocmVtYWluaW5nVGltZSAqIDEwMDAsIG1heFRpbWVvdXRUaW1lKSwgMCksXG4gICAgICApXG4gICAgfVxuXG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlmIChmb3JjZUxvZ091dCkgY2xlYXJUaW1lb3V0KGZvcmNlTG9nT3V0KVxuICAgIH1cbiAgfSwgW3Rva2VuRXhwaXJhdGlvbiwgY2xvc2VBbGxNb2RhbHMsIGkxOG4sIHJlZGlyZWN0VG9JbmFjdGl2aXR5Um91dGUsIHJldm9rZVRva2VuQW5kRXhwaXJlXSlcblxuICByZXR1cm4gKFxuICAgIDxDb250ZXh0LlByb3ZpZGVyXG4gICAgICB2YWx1ZT17e1xuICAgICAgICBmZXRjaEZ1bGxVc2VyLFxuICAgICAgICBsb2dPdXQsXG4gICAgICAgIHBlcm1pc3Npb25zLFxuICAgICAgICByZWZyZXNoQ29va2llLFxuICAgICAgICByZWZyZXNoQ29va2llQXN5bmMsXG4gICAgICAgIHJlZnJlc2hQZXJtaXNzaW9ucyxcbiAgICAgICAgc2V0VXNlcixcbiAgICAgICAgdG9rZW46IHRva2VuSW5NZW1vcnksXG4gICAgICAgIHVzZXIsXG4gICAgICB9fVxuICAgID5cbiAgICAgIHtjaGlsZHJlbn1cbiAgICA8L0NvbnRleHQuUHJvdmlkZXI+XG4gIClcbn1cblxuZXhwb3J0IGNvbnN0IHVzZUF1dGggPSA8VCA9IFVzZXIsPigpOiBBdXRoQ29udGV4dDxUPiA9PiB1c2VDb250ZXh0KENvbnRleHQpIGFzIEF1dGhDb250ZXh0PFQ+XG4iXSwibmFtZXMiOlsiQXV0aFByb3ZpZGVyIiwidXNlQXV0aCIsIkNvbnRleHQiLCJjcmVhdGVDb250ZXh0IiwibWF4VGltZW91dFRpbWUiLCJjaGlsZHJlbiIsInVzZXIiLCJzZXRVc2VyIiwidXNlU3RhdGUiLCJ0b2tlbkluTWVtb3J5Iiwic2V0VG9rZW5Jbk1lbW9yeSIsInRva2VuRXhwaXJhdGlvbiIsInNldFRva2VuRXhwaXJhdGlvbiIsInBhdGhuYW1lIiwidXNlTG9jYXRpb24iLCJwdXNoIiwidXNlSGlzdG9yeSIsImNvZGUiLCJ1c2VMb2NhbGUiLCJjb25maWciLCJ1c2VDb25maWciLCJhZG1pbiIsImF1dG9Mb2dpbiIsImluYWN0aXZpdHlSb3V0ZSIsImxvZ291dEluYWN0aXZpdHlSb3V0ZSIsInVzZXJTbHVnIiwicm91dGVzIiwiYXBpIiwic2VydmVyVVJMIiwicGVybWlzc2lvbnMiLCJzZXRQZXJtaXNzaW9ucyIsImkxOG4iLCJ1c2VUcmFuc2xhdGlvbiIsImNsb3NlQWxsTW9kYWxzIiwib3Blbk1vZGFsIiwidXNlTW9kYWwiLCJsYXN0TG9jYXRpb25DaGFuZ2UiLCJzZXRMYXN0TG9jYXRpb25DaGFuZ2UiLCJkZWJvdW5jZWRMb2NhdGlvbkNoYW5nZSIsInVzZURlYm91bmNlIiwiaWQiLCJyZWRpcmVjdFRvSW5hY3Rpdml0eVJvdXRlIiwidXNlQ2FsbGJhY2siLCJ3aW5kb3ciLCJsb2NhdGlvbiIsInN0YXJ0c1dpdGgiLCJyZWRpcmVjdFBhcmFtIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwicmVwbGFjZSIsInJldm9rZVRva2VuQW5kRXhwaXJlIiwidW5kZWZpbmVkIiwic2V0VG9rZW5BbmRFeHBpcmF0aW9uIiwianNvbiIsInRva2VuIiwicmVmcmVzaGVkVG9rZW4iLCJleHAiLCJyZWZyZXNoQ29va2llIiwiZm9yY2VSZWZyZXNoIiwibm93IiwiTWF0aCIsInJvdW5kIiwiRGF0ZSIsImdldFRpbWUiLCJyZW1haW5pbmdUaW1lIiwic2V0VGltZW91dCIsInJlcXVlc3QiLCJyZXF1ZXN0cyIsInBvc3QiLCJoZWFkZXJzIiwibGFuZ3VhZ2UiLCJzdGF0dXMiLCJlIiwidG9hc3QiLCJlcnJvciIsIm1lc3NhZ2UiLCJyZWZyZXNoQ29va2llQXN5bmMiLCJza2lwU2V0VXNlciIsImxvZ091dCIsInJlZnJlc2hQZXJtaXNzaW9ucyIsInBhcmFtcyIsImxvY2FsZSIsImdldCIsInFzIiwic3RyaW5naWZ5IiwiRXJyb3IiLCJmZXRjaEZ1bGxVc2VyIiwiUmVhY3QiLCJwcmVmaWxsT25seSIsImF1dG9Mb2dpblJlc3VsdCIsImJvZHkiLCJKU09OIiwiZW1haWwiLCJwYXNzd29yZCIsImF1dG9Mb2dpbkpzb24iLCJ1c2VFZmZlY3QiLCJyZW1pbmRlciIsIm1heCIsIm1pbiIsImNsZWFyVGltZW91dCIsImZvcmNlTG9nT3V0IiwiUHJvdmlkZXIiLCJ2YWx1ZSIsInVzZUNvbnRleHQiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O0lBbUJhQSxZQUFZO2VBQVpBOztJQTBSQUMsT0FBTztlQUFQQTs7O3VCQTdTWTsyREFDVjsrREFDb0U7OEJBQ3BEO2dDQUNTOytCQUNsQjtxQkFLRztvRUFDRDt3QkFDRTt3QkFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFMUIsTUFBTUMsd0JBQVVDLElBQUFBLG9CQUFhLEVBQUMsQ0FBQztBQUUv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