(code: string)
| 101 | |
| 102 | // Handle auth code from deep link (exported for IPC handlers) |
| 103 | export async function handleAuthCode(code: string): Promise<void> { |
| 104 | console.log("[Auth] Handling auth code:", code.slice(0, 8) + "...") |
| 105 | |
| 106 | try { |
| 107 | const authData = await authManager.exchangeCode(code) |
| 108 | console.log("[Auth] Success for user:", authData.user.email) |
| 109 | |
| 110 | // Track successful authentication |
| 111 | trackAuthCompleted(authData.user.id, authData.user.email) |
| 112 | |
| 113 | // Fetch and set subscription plan for analytics |
| 114 | try { |
| 115 | const planData = await authManager.fetchUserPlan() |
| 116 | if (planData) { |
| 117 | setSubscriptionPlan(planData.plan) |
| 118 | } |
| 119 | } catch (e) { |
| 120 | console.warn("[Auth] Failed to fetch user plan for analytics:", e) |
| 121 | } |
| 122 | |
| 123 | // Set desktop token cookie using persist:main partition |
| 124 | const ses = session.fromPartition("persist:main") |
| 125 | try { |
| 126 | // First remove any existing cookie to avoid HttpOnly conflict |
| 127 | await ses.cookies.remove(getBaseUrl(), "x-desktop-token") |
| 128 | await ses.cookies.set({ |
| 129 | url: getBaseUrl(), |
| 130 | name: "x-desktop-token", |
| 131 | value: authData.token, |
| 132 | expirationDate: Math.floor( |
| 133 | new Date(authData.expiresAt).getTime() / 1000, |
| 134 | ), |
| 135 | httpOnly: false, |
| 136 | secure: getBaseUrl().startsWith("https"), |
| 137 | sameSite: "lax" as const, |
| 138 | }) |
| 139 | console.log("[Auth] Desktop token cookie set") |
| 140 | } catch (cookieError) { |
| 141 | // Cookie setting is optional - auth data is already saved to disk |
| 142 | console.warn("[Auth] Cookie set failed (non-critical):", cookieError) |
| 143 | } |
| 144 | |
| 145 | // Notify all windows and reload them to show app |
| 146 | const windows = getAllWindows() |
| 147 | for (const win of windows) { |
| 148 | try { |
| 149 | if (win.isDestroyed()) continue |
| 150 | win.webContents.send("auth:success", authData.user) |
| 151 | |
| 152 | // Use stable window ID (main, window-2, etc.) instead of Electron's numeric ID |
| 153 | const stableId = windowManager.getStableId(win) |
| 154 | |
| 155 | if (process.env.ELECTRON_RENDERER_URL) { |
| 156 | // Pass window ID via query param for dev mode |
| 157 | const url = new URL(process.env.ELECTRON_RENDERER_URL) |
| 158 | url.searchParams.set("windowId", stableId) |
| 159 | win.loadURL(url.toString()) |
| 160 | } else { |
no test coverage detected