(data)
| 652 | } |
| 653 | |
| 654 | async function submitLogin(data) { |
| 655 | if (__loginInFlight) return; |
| 656 | __loginInFlight = true; |
| 657 | |
| 658 | const payload = { |
| 659 | username: String(data.username || '').trim(), |
| 660 | password: String(data.password || '').trim(), |
| 661 | remember_me: data.remember_me ? 1 : 0 |
| 662 | }; |
| 663 | |
| 664 | setLastLoginData(payload); |
| 665 | window.__lastLoginData = payload; |
| 666 | |
| 667 | try { |
| 668 | await primeCsrfStrict(); |
| 669 | |
| 670 | // Attempt #1 — JSON |
| 671 | let res = await fetchWithCsrf('/api/auth/auth.php', { |
| 672 | method: 'POST', |
| 673 | credentials: 'include', |
| 674 | headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }, |
| 675 | body: JSON.stringify(payload) |
| 676 | }); |
| 677 | let body = await safeJson(res); |
| 678 | |
| 679 | // TOTP requested? |
| 680 | if (await sniffTOTP(res, body)) { |
| 681 | if (typeof window.__frResetLoginFailure === 'function') { |
| 682 | window.__frResetLoginFailure(); |
| 683 | } |
| 684 | try { await primeCsrfStrict(); } catch (e) { } |
| 685 | window.pendingTOTP = true; |
| 686 | try { |
| 687 | const auth = await import(withBase('/js/auth.js?v={{APP_QVER}}')); |
| 688 | if (typeof auth.openTOTPLoginModal === 'function') auth.openTOTPLoginModal(); |
| 689 | } catch (e) { } |
| 690 | return; |
| 691 | } |
| 692 | |
| 693 | // Full success (no TOTP) |
| 694 | if (body && (body.success || body.status === 'ok' || body.authenticated)) { |
| 695 | if (typeof window.__frResetLoginFailure === 'function') { |
| 696 | window.__frResetLoginFailure(); |
| 697 | } |
| 698 | |
| 699 | await syncPermissionsToLocalStorage(); |
| 700 | return afterLogin(); |
| 701 | } |
| 702 | |
| 703 | // Cookie set but non-JSON body — double check session |
| 704 | if (!body && await isAuthedNow()) { |
| 705 | if (typeof window.__frResetLoginFailure === 'function') { |
| 706 | window.__frResetLoginFailure(); |
| 707 | } |
| 708 | |
| 709 | await syncPermissionsToLocalStorage(); |
| 710 | |
| 711 | return afterLogin(); |
no test coverage detected