Skip to content

Commit d6c7970

Browse files
committed
Fix baseline Windows OAuth login
1 parent a0d9c90 commit d6c7970

3 files changed

Lines changed: 68 additions & 2 deletions

File tree

cli/src/utils/__tests__/fingerprint.test.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { describe, test, expect } from 'bun:test'
22

3-
import { getFingerprintType, generateFingerprintIdSync } from '../fingerprint'
3+
import {
4+
getFingerprintType,
5+
generateFingerprintIdSync,
6+
withTimeout,
7+
} from '../fingerprint'
48

59
describe('fingerprint utilities', () => {
610
describe('getFingerprintType', () => {
@@ -141,4 +145,20 @@ describe('fingerprint utilities', () => {
141145
})
142146
})
143147
})
148+
149+
describe('withTimeout', () => {
150+
test('resolves when the promise finishes before the timeout', async () => {
151+
await expect(
152+
withTimeout(Promise.resolve('ok'), 100, 'too slow'),
153+
).resolves.toBe('ok')
154+
})
155+
156+
test('rejects when the promise exceeds the timeout', async () => {
157+
const neverResolves = new Promise<string>(() => {})
158+
159+
await expect(withTimeout(neverResolves, 1, 'too slow')).rejects.toThrow(
160+
'too slow',
161+
)
162+
})
163+
})
144164
})

cli/src/utils/fingerprint.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,28 @@ import { logger } from './logger'
2020
let machineIdModule: typeof import('node-machine-id') | null = null
2121
let systeminformationModule: typeof import('systeminformation') | null = null
2222

23+
const ENHANCED_FINGERPRINT_TIMEOUT_MS = 3000
24+
25+
export function withTimeout<T>(
26+
promise: Promise<T>,
27+
timeoutMs: number,
28+
timeoutMessage: string,
29+
): Promise<T> {
30+
let timeout: ReturnType<typeof setTimeout> | null = null
31+
32+
const timeoutPromise = new Promise<never>((_, reject) => {
33+
timeout = setTimeout(() => {
34+
reject(new Error(timeoutMessage))
35+
}, timeoutMs)
36+
})
37+
38+
return Promise.race([promise, timeoutPromise]).finally(() => {
39+
if (timeout) {
40+
clearTimeout(timeout)
41+
}
42+
})
43+
}
44+
2345
async function getMachineId(): Promise<string> {
2446
if (!machineIdModule) {
2547
machineIdModule = await import('node-machine-id')
@@ -162,7 +184,11 @@ export function getFingerprintId(): Promise<string> {
162184
*/
163185
export async function calculateFingerprint(): Promise<string> {
164186
try {
165-
const fingerprint = await calculateEnhancedFingerprint()
187+
const fingerprint = await withTimeout(
188+
calculateEnhancedFingerprint(),
189+
ENHANCED_FINGERPRINT_TIMEOUT_MS,
190+
`Enhanced CLI fingerprinting timed out after ${ENHANCED_FINGERPRINT_TIMEOUT_MS}ms`,
191+
)
166192
logger.debug(
167193
{
168194
fingerprintType: 'enhanced_cli',

cli/src/utils/open-url.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os from 'os'
2+
import { spawn } from 'child_process'
23

34
import open from 'open'
45

@@ -16,6 +17,25 @@ import { logger } from './logger'
1617
* @returns `true` if the browser was (likely) opened, `false` if skipped.
1718
*/
1819
export async function safeOpen(url: string): Promise<boolean> {
20+
if (os.platform() === 'win32') {
21+
try {
22+
const subprocess = spawn(
23+
'rundll32.exe',
24+
['url.dll,FileProtocolHandler', url],
25+
{
26+
detached: true,
27+
stdio: 'ignore',
28+
windowsHide: true,
29+
},
30+
)
31+
subprocess.unref()
32+
return true
33+
} catch (err) {
34+
logger.error(err, 'Failed to open browser with Windows URL handler')
35+
return false
36+
}
37+
}
38+
1939
if (os.platform() === 'linux') {
2040
const env = getCliEnv()
2141
const hasDisplay = Boolean(env.DISPLAY || env.WAYLAND_DISPLAY)

0 commit comments

Comments
 (0)