Primeiro Commit v0.beta1
This commit is contained in:
295
scripts/refresh-auth-state.mjs
Normal file
295
scripts/refresh-auth-state.mjs
Normal file
@@ -0,0 +1,295 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { createRequire } from "node:module";
|
||||
import { fileURLToPath, pathToFileURL } from "node:url";
|
||||
import {
|
||||
DISPLAY_CHROME_PATH,
|
||||
DISPLAY_META_PATH,
|
||||
DISPLAY_RUNTIME_HOME,
|
||||
DISPLAY_PROFILE_DIR,
|
||||
DISPLAY_STATE_PATH,
|
||||
ensureDir,
|
||||
ensureParentDir,
|
||||
ensureRuntimeTree,
|
||||
resolveChromePath,
|
||||
resolveMetaWritePath,
|
||||
resolveProfileDir,
|
||||
resolveRuntimeHome,
|
||||
resolveStateWritePath,
|
||||
} from "./lib/runtime-paths.mjs";
|
||||
import { parseArgs } from "./lib/cli-shared.mjs";
|
||||
import { extractClientBin } from "./lib/auth-shared.mjs";
|
||||
|
||||
const DEFAULT_URL =
|
||||
"https://salesintelligence-dv.oracle.com/ui/dv/ui/project.jsp?pageid=visualAnalyzer&reportmode=presentation&reportpath=%2F%40Catalog%2Fshared%2FTeam%20Sharing%20Area%2FLAD%2FLAD%20Sales%20Operations%2FLAD%20Production%2FLAD%20Knowledge%20One%20View";
|
||||
const scriptsDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
const skillHome = path.resolve(scriptsDir, "..");
|
||||
const skillsHome = path.resolve(skillHome, "..");
|
||||
|
||||
function usage() {
|
||||
return `Refresh Oracle Sales Intelligence auth by opening Chrome.
|
||||
|
||||
This is an optional development and troubleshooting helper. Daily use should prefer scripts/refresh-auth-direct.mjs.
|
||||
|
||||
Usage:
|
||||
node scripts/refresh-auth-state.mjs [options]
|
||||
|
||||
Options:
|
||||
--runtime-home <dir> Override workspace runtime root (default: ${DISPLAY_RUNTIME_HOME})
|
||||
--state-path <file> Override auth-state.json output path (default: ${DISPLAY_STATE_PATH})
|
||||
--meta-path <file> Override session-meta.json output path (default: ${DISPLAY_META_PATH})
|
||||
--profile-dir <dir> Override Chrome profile directory (default: ${DISPLAY_PROFILE_DIR})
|
||||
--chrome-path <file> Override Chrome executable path (default: ${DISPLAY_CHROME_PATH})
|
||||
--url <url> Target Oracle DV workbook URL
|
||||
--timeout-ms <ms> Wait time for authenticated Oracle DV page (default: 600000)
|
||||
--help Show this help
|
||||
`;
|
||||
}
|
||||
|
||||
async function pathExists(targetPath) {
|
||||
try {
|
||||
await fs.access(targetPath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function uniquePaths(values) {
|
||||
const seen = new Set();
|
||||
const result = [];
|
||||
for (const value of values.filter(Boolean)) {
|
||||
const resolved = path.resolve(value);
|
||||
if (seen.has(resolved)) continue;
|
||||
seen.add(resolved);
|
||||
result.push(resolved);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function bundledRuntimePackageCandidates(packageName) {
|
||||
const execDir = path.dirname(process.execPath || "");
|
||||
const envNodeModules = [
|
||||
process.env.CODEX_NODE_MODULES,
|
||||
process.env.CODEX_BUNDLED_NODE_MODULES,
|
||||
process.env.NODE_PATH,
|
||||
].filter(Boolean);
|
||||
|
||||
const packageJsonCandidates = [];
|
||||
for (const nodeModulesPath of envNodeModules) {
|
||||
for (const basePath of String(nodeModulesPath).split(path.delimiter)) {
|
||||
if (!basePath) continue;
|
||||
packageJsonCandidates.push(path.join(basePath, packageName, "package.json"));
|
||||
}
|
||||
}
|
||||
|
||||
if (process.env.CODEX_PRIMARY_RUNTIME_HOME) {
|
||||
packageJsonCandidates.push(
|
||||
path.join(
|
||||
process.env.CODEX_PRIMARY_RUNTIME_HOME,
|
||||
"dependencies",
|
||||
"node",
|
||||
"node_modules",
|
||||
packageName,
|
||||
"package.json",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
packageJsonCandidates.push(
|
||||
path.join(execDir, "node_modules", packageName, "package.json"),
|
||||
path.join(execDir, "..", "node_modules", packageName, "package.json"),
|
||||
path.join(execDir, "..", "..", "node_modules", packageName, "package.json"),
|
||||
path.join(
|
||||
os.homedir(),
|
||||
".cache",
|
||||
"codex-runtimes",
|
||||
"codex-primary-runtime",
|
||||
"dependencies",
|
||||
"node",
|
||||
"node_modules",
|
||||
packageName,
|
||||
"package.json",
|
||||
),
|
||||
);
|
||||
|
||||
return uniquePaths(packageJsonCandidates);
|
||||
}
|
||||
|
||||
async function loadPlaywright() {
|
||||
const packageNames = ["playwright", "playwright-core"];
|
||||
|
||||
for (const packageName of packageNames) {
|
||||
try {
|
||||
return {
|
||||
runtime: await import(packageName),
|
||||
sourceLabel: `local-module:${packageName}`,
|
||||
};
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const sharedSkillPackageJson = path.join(skillsHome, "playwright", "package.json");
|
||||
if (await pathExists(sharedSkillPackageJson)) {
|
||||
const requireFromSharedSkill = createRequire(sharedSkillPackageJson);
|
||||
for (const packageName of packageNames) {
|
||||
try {
|
||||
return {
|
||||
runtime: requireFromSharedSkill(packageName),
|
||||
sourceLabel: `shared-skill:${packageName}`,
|
||||
};
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
for (const packageName of packageNames) {
|
||||
for (const packageJsonPath of bundledRuntimePackageCandidates(packageName)) {
|
||||
if (!(await pathExists(packageJsonPath))) continue;
|
||||
try {
|
||||
const requireFromBundledRuntime = createRequire(packageJsonPath);
|
||||
return {
|
||||
runtime: requireFromBundledRuntime(packageName),
|
||||
sourceLabel: `bundled-runtime:${packageJsonPath}`,
|
||||
};
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
[
|
||||
"Could not load Playwright for the browser auth helper.",
|
||||
"Tried local module resolution, ~/.codex/skills/playwright, and bundled Codex runtime locations.",
|
||||
"Install a shared Playwright runtime under ~/.codex/skills/playwright or run this helper from a Codex environment with bundled node_modules.",
|
||||
].join(" "),
|
||||
);
|
||||
}
|
||||
|
||||
async function ensureChromeExecutable(chromePath) {
|
||||
try {
|
||||
await fs.access(chromePath);
|
||||
} catch {
|
||||
throw new Error(
|
||||
`Could not find a Chrome executable at ${chromePath}. Pass --chrome-path or set ORACLE_SI_CHROME_PATH to a valid Chrome installation.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function main(argv = process.argv.slice(2)) {
|
||||
const args = parseArgs(argv);
|
||||
if (args.help === "true") {
|
||||
console.log(usage());
|
||||
return;
|
||||
}
|
||||
const runtimeHome = resolveRuntimeHome(args["runtime-home"]);
|
||||
await ensureRuntimeTree(runtimeHome);
|
||||
const statePath = resolveStateWritePath({ explicitPath: args["state-path"], runtimeHome });
|
||||
const metaPath = resolveMetaWritePath({ explicitPath: args["meta-path"], runtimeHome });
|
||||
const profileDir = resolveProfileDir({ explicitPath: args["profile-dir"], runtimeHome });
|
||||
const chromePath = resolveChromePath(args["chrome-path"]);
|
||||
const targetUrl = args.url || process.env.ORACLE_SI_TARGET_URL || DEFAULT_URL;
|
||||
const timeoutMs = Number(args["timeout-ms"] || 10 * 60 * 1000);
|
||||
|
||||
await ensureChromeExecutable(chromePath);
|
||||
const { runtime: playwrightRuntime, sourceLabel } = await loadPlaywright();
|
||||
const { chromium } = playwrightRuntime;
|
||||
|
||||
await ensureParentDir(statePath);
|
||||
await ensureParentDir(metaPath);
|
||||
await ensureDir(profileDir);
|
||||
|
||||
console.log(`Opening Chrome profile at ${profileDir}`);
|
||||
console.log(`Using browser automation runtime: ${sourceLabel}`);
|
||||
console.log("Complete Oracle login in the opened window if prompted.");
|
||||
|
||||
const context = await chromium.launchPersistentContext(profileDir, {
|
||||
executablePath: chromePath,
|
||||
headless: false,
|
||||
ignoreHTTPSErrors: true,
|
||||
viewport: { width: 1600, height: 900 },
|
||||
});
|
||||
|
||||
let headerMeta = null;
|
||||
const requestListener = (request) => {
|
||||
if (headerMeta) return;
|
||||
if (!request.url().includes("/ui/dv/ui/api/")) return;
|
||||
const headers = request.headers();
|
||||
const csrfToken = headers["x-csrf-token"] || null;
|
||||
const clientBin = headers["x-bitech-clientbin"] || null;
|
||||
if (!csrfToken || !clientBin) return;
|
||||
headerMeta = {
|
||||
xCsrfToken: csrfToken,
|
||||
xBitechClientbin: clientBin,
|
||||
referer: headers.referer || targetUrl,
|
||||
targetUrl,
|
||||
capturedAt: new Date().toISOString(),
|
||||
};
|
||||
};
|
||||
context.on("request", requestListener);
|
||||
|
||||
try {
|
||||
const page = context.pages()[0] ?? (await context.newPage());
|
||||
await page.goto(targetUrl, { waitUntil: "domcontentloaded", timeout: 120000 });
|
||||
|
||||
const deadline = Date.now() + timeoutMs;
|
||||
while (Date.now() < deadline) {
|
||||
await page.waitForTimeout(2000);
|
||||
const url = page.url();
|
||||
const title = await page.title().catch(() => "");
|
||||
console.log(`Waiting for Oracle Analytics session: ${url}`);
|
||||
|
||||
const authenticated =
|
||||
url.startsWith("https://salesintelligence-dv.oracle.com/") &&
|
||||
!url.includes("signon.oracle.com") &&
|
||||
!url.includes("signon-int.oracle.com") &&
|
||||
/Oracle Analytics|LAD Knowledge One View/i.test(title || url);
|
||||
|
||||
if (!authenticated) continue;
|
||||
|
||||
const html = await page.content();
|
||||
const fallbackClientBin = extractClientBin(html);
|
||||
|
||||
if (!headerMeta) {
|
||||
await page.reload({ waitUntil: "domcontentloaded" }).catch(() => {});
|
||||
await page.waitForTimeout(4000);
|
||||
}
|
||||
|
||||
if (!headerMeta?.xBitechClientbin && fallbackClientBin) {
|
||||
headerMeta = {
|
||||
...(headerMeta || {}),
|
||||
xCsrfToken: headerMeta?.xCsrfToken || null,
|
||||
xBitechClientbin: fallbackClientBin,
|
||||
referer: headerMeta?.referer || targetUrl,
|
||||
targetUrl,
|
||||
capturedAt: new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
if (!headerMeta?.xCsrfToken || !headerMeta?.xBitechClientbin) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const state = await context.storageState();
|
||||
await fs.writeFile(statePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
||||
await fs.writeFile(metaPath, `${JSON.stringify(headerMeta, null, 2)}\n`, "utf8");
|
||||
|
||||
console.log(`Saved auth state to ${statePath}`);
|
||||
console.log(`Saved session metadata to ${metaPath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Timed out waiting for an authenticated Oracle DV page after ${timeoutMs}ms.`);
|
||||
} finally {
|
||||
context.off("request", requestListener);
|
||||
await context.close().catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
const entryUrl = process.argv[1] ? pathToFileURL(path.resolve(process.argv[1])).href : null;
|
||||
if (import.meta.url === entryUrl) {
|
||||
main().catch((error) => {
|
||||
console.error(error.message);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user