payload
Version:
Node, React and MongoDB Headless CMS and Application Framework
359 lines (358 loc) • 34.6 kB
JavaScript
;
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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