131 lines
4.6 KiB
JavaScript
131 lines
4.6 KiB
JavaScript
/** Read the local credential; stop at the normal MFA challenge, without submitting a code. */
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
const {
|
|
chromium,
|
|
} = require('C:/Users/macbook/.cache/codex-runtimes/codex-primary-runtime/dependencies/node/node_modules/playwright');
|
|
const root = path.resolve(__dirname, '..');
|
|
const directory = path.join(
|
|
root,
|
|
'storage/app/private/investmoz-v2/portal-audit',
|
|
);
|
|
const base = 'http://127.0.0.1:18097';
|
|
const target = 'desk_restore_20261009_174726_test:55441';
|
|
const credential = JSON.parse(
|
|
fs.readFileSync(
|
|
path.join(directory, 'investor-mfa-qa-private.json'),
|
|
'utf8',
|
|
),
|
|
);
|
|
const proof = {
|
|
captured_at: new Date().toISOString(),
|
|
base,
|
|
target,
|
|
account_id: 18,
|
|
isolated_browser_context: true,
|
|
events: [],
|
|
last_step: 'initialize',
|
|
password_changed: false,
|
|
mfa_changed: false,
|
|
mfa_code_submitted: false,
|
|
active_writes: 0,
|
|
};
|
|
let browser;
|
|
(async () => {
|
|
if (
|
|
credential.actor_id !== 18 ||
|
|
credential.email !== 'investor-mfa-qa@example.invalid'
|
|
)
|
|
throw new Error();
|
|
browser = await chromium.launch({
|
|
headless: true,
|
|
executablePath:
|
|
'C:/Users/macbook/AppData/Local/ms-playwright/chromium-1243/chrome-win64/chrome.exe',
|
|
});
|
|
const context = await browser.newContext({ locale: 'pt-MZ' });
|
|
let confirmed = false;
|
|
await context.route('**/*', async (route) => {
|
|
const request = route.request();
|
|
if (
|
|
new URL(request.url()).origin !== base ||
|
|
(!['GET', 'HEAD'].includes(request.method()) &&
|
|
(!confirmed || new URL(request.url()).pathname !== '/login'))
|
|
) {
|
|
return route.abort();
|
|
}
|
|
await route.continue();
|
|
});
|
|
const page = await context.newPage();
|
|
page.on('response', (response) => {
|
|
const request = response.request(),
|
|
url = new URL(response.url());
|
|
if (['/login', '/two-factor-challenge'].includes(url.pathname)) {
|
|
const headers = response.headers();
|
|
proof.events.push({
|
|
method: request.method(),
|
|
path: url.pathname,
|
|
status: response.status(),
|
|
target: headers['x-investmoz-qa-target'] || null,
|
|
redirect_path: headers.location
|
|
? new URL(headers.location, base).pathname
|
|
: null,
|
|
});
|
|
}
|
|
});
|
|
proof.last_step = 'load_login';
|
|
const response = await page.goto(base + '/login', {
|
|
waitUntil: 'networkidle',
|
|
});
|
|
if ((await response.allHeaders())['x-investmoz-qa-target'] !== target)
|
|
throw new Error();
|
|
confirmed = true;
|
|
await page.locator('[aria-label="Conta de ensaio QA"]').waitFor();
|
|
proof.qa18_notice_visible = (
|
|
await page.locator('[aria-label="Conta de ensaio QA"]').innerText()
|
|
).includes('conta 18');
|
|
proof.last_step = 'submit_local_credential';
|
|
await page.locator('#email').fill(credential.email);
|
|
await page.locator('#password').fill(credential.password);
|
|
await page.locator('[data-test="login-button"]').click();
|
|
await page.waitForURL(base + '/two-factor-challenge', { timeout: 20000 });
|
|
proof.last_step = 'normal_mfa_challenge_visible';
|
|
proof.final_path = new URL(page.url()).pathname;
|
|
proof.account18_mfa_visible = (
|
|
await page.locator('body').innerText()
|
|
).includes(credential.email);
|
|
proof.passed = proof.qa18_notice_visible && proof.account18_mfa_visible;
|
|
proof.cookie_attributes = (await context.cookies()).map(
|
|
({ name, domain, path, secure, httpOnly, sameSite }) => ({
|
|
name,
|
|
domain,
|
|
path,
|
|
secure,
|
|
httpOnly,
|
|
sameSite,
|
|
}),
|
|
);
|
|
await context.close();
|
|
})()
|
|
.catch(() => {
|
|
// Playwright errors can include filled input values: never export their messages/stacks.
|
|
proof.passed = false;
|
|
proof.error =
|
|
'Browser check failed; credential values and error details withheld.';
|
|
process.exitCode = 1;
|
|
})
|
|
.finally(async () => {
|
|
if (browser) await browser.close();
|
|
credential.password = undefined;
|
|
credential.totp_secret = undefined;
|
|
const name =
|
|
'investor-credential-browser-' +
|
|
proof.captured_at.replace(/[^0-9TZ-]/g, '-') +
|
|
'.json';
|
|
fs.writeFileSync(
|
|
path.join(directory, name),
|
|
JSON.stringify(proof, null, 2),
|
|
{ mode: 0o600 },
|
|
);
|
|
console.log(JSON.stringify(proof));
|
|
});
|