The sessions required for Internal SR API calls are now loaded via an iframe
This commit is contained in:
54
src/features/opportunities/internal-sr-session.js
Normal file
54
src/features/opportunities/internal-sr-session.js
Normal file
@@ -0,0 +1,54 @@
|
||||
function createInternalSrSession({ query, environment }) {
|
||||
const { document, setTimeout } = environment;
|
||||
let recovery = null;
|
||||
const wait = duration => new Promise(resolve => setTimeout(resolve, duration));
|
||||
const now = () => environment.performance?.now() ?? Date.now();
|
||||
async function warmSession(id) {
|
||||
const frame = document.createElement("iframe");
|
||||
frame.src = "https://eeho.fa.us2.oraclecloud.com/fscmUI/redwood/service/ec/container/sr/edit?srNumber=SR0001421040&srId=302963804324543&view=showisr";
|
||||
frame.title = "Internal SR session initialization";
|
||||
frame.tabIndex = -1;
|
||||
frame.setAttribute("aria-hidden", "true");
|
||||
frame.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
|
||||
frame.style.cssText = "position:fixed;width:1px;height:1px;left:-10000px;top:0;border:0;opacity:0;pointer-events:none;";
|
||||
let blocked = false;
|
||||
let loaded = false;
|
||||
frame.addEventListener("error", () => { blocked = true; });
|
||||
frame.addEventListener("load", () => { loaded = true; });
|
||||
try {
|
||||
if (!document.body) throw new Error("The current page cannot initialize the Internal SR session.");
|
||||
document.body.append(frame);
|
||||
const deadline = now() + 60000;
|
||||
for (let attempt = 0; now() < deadline; attempt += 1) {
|
||||
// Check immediately, then briefly poll faster before backing off.
|
||||
if (attempt > 0) await wait(Math.min(attempt <= 4 ? 250 : 1000, deadline - now()));
|
||||
if (now() >= deadline) break;
|
||||
if (blocked) throw new Error("The Internal SR session iframe could not be loaded. Sign in manually and try again.");
|
||||
const result = await query(id);
|
||||
if (result?.ok) return { id, result };
|
||||
if (result?.httpStatus !== 401) throw new Error(result?.error || "Unable to load Internal SR details.");
|
||||
}
|
||||
throw new Error(`Internal SR session timed out after 60 seconds: the API still returned HTTP 401. ${loaded ? "The iframe emitted a load event, but authentication was not confirmed." : "The iframe did not emit a load event."} Sign in manually and try again.`);
|
||||
} finally {
|
||||
// Stop remaining page resources without stopping the caller's page.
|
||||
try { frame.contentWindow?.stop(); } catch { /* Redirects can make the frame cross-origin. */ }
|
||||
frame.src = "about:blank";
|
||||
frame.remove();
|
||||
}
|
||||
}
|
||||
async function request(id) {
|
||||
let result = await query(id);
|
||||
if (!result?.ok && result?.httpStatus === 401) {
|
||||
if (!recovery) {
|
||||
recovery = warmSession(id);
|
||||
const pending = recovery;
|
||||
pending.finally(() => { if (recovery === pending) recovery = null; }).catch(() => {});
|
||||
}
|
||||
const recovered = await recovery;
|
||||
result = recovered.id === id ? recovered.result : await query(id);
|
||||
}
|
||||
if (!result?.ok) throw new Error(result?.error || "Unable to load Internal SR details.");
|
||||
return result.items;
|
||||
}
|
||||
return { request };
|
||||
}
|
||||
Reference in New Issue
Block a user