Various fixes and cleanup, regressions from prior commits.

This commit is contained in:
2025-12-04 03:40:59 +00:00
parent 6124fa6c01
commit 9976e05696
10 changed files with 87 additions and 67 deletions
+7 -3
View File
@@ -153,7 +153,7 @@ async function authenticateUser() {
emit('auth-error', { message, cancelled })
return
}
try { await setSessionCookie(result.session_token) } catch (error) {
try { await setSessionCookie(result) } catch (error) {
loading.value = false
const message = error?.message || 'Failed to establish session'
showMessage(message, 'error', 4000)
@@ -186,9 +186,13 @@ function openProfile() {
if (profileWindow) profileWindow.focus()
}
async function setSessionCookie(sessionToken) {
async function setSessionCookie(result) {
if (!result?.session_token) {
console.error('setSessionCookie called with missing session_token:', result)
throw new Error('Authentication response missing session_token')
}
return await apiJson('/auth/api/set-session', {
method: 'POST', headers: { Authorization: `Bearer ${sessionToken}` }
method: 'POST', headers: { Authorization: `Bearer ${result.session_token}` }
})
}
+23 -9
View File
@@ -38,18 +38,21 @@ export const useAuthStore = defineStore('auth', {
}, duration)
}
},
async setSessionCookie(sessionToken) {
const result = await apiJson('/auth/api/set-session', {
async setSessionCookie(result) {
if (!result?.session_token) {
console.error('setSessionCookie called with missing session_token:', result)
throw new Error('Authentication response missing session_token')
}
return await apiJson('/auth/api/set-session', {
method: 'POST',
headers: {'Authorization': `Bearer ${sessionToken}`},
headers: {'Authorization': `Bearer ${result.session_token}`},
})
return result
},
async register() {
this.isLoading = true
try {
const result = await register()
await this.setSessionCookie(result.session_token)
await this.setSessionCookie(result)
await this.loadUserInfo()
this.selectView()
return result
@@ -62,7 +65,7 @@ export const useAuthStore = defineStore('auth', {
try {
const result = await authenticate()
await this.setSessionCookie(result.session_token)
await this.setSessionCookie(result)
await this.loadUserInfo()
this.selectView()
@@ -83,7 +86,12 @@ export const useAuthStore = defineStore('auth', {
this.userInfo = await apiJson('/auth/api/user-info', { method: 'POST' })
console.log('User info loaded:', this.userInfo)
} catch (error) {
this.showMessage(error.message || 'Failed to load user info', 'error', 5000)
// Suppress toast for 401/403 errors - the auth iframe will handle these
if (error.status === 401 || error.status === 403) {
console.log('Authentication required:', error.message)
} else {
this.showMessage(error.message || 'Failed to load user info', 'error', 5000)
}
throw error
}
},
@@ -113,7 +121,10 @@ export const useAuthStore = defineStore('auth', {
location.reload()
} catch (error) {
console.error('Logout error:', error)
this.showMessage(error.message, 'error')
// Suppress toast for 401/403 errors - the auth iframe will handle these
if (error.status !== 401 && error.status !== 403) {
this.showMessage(error.message, 'error')
}
}
},
async logoutEverywhere() {
@@ -123,7 +134,10 @@ export const useAuthStore = defineStore('auth', {
location.reload()
} catch (error) {
console.error('Logout-all error:', error)
this.showMessage(error.message, 'error')
// Suppress toast for 401/403 errors - the auth iframe will handle these
if (error.status !== 401 && error.status !== 403) {
this.showMessage(error.message, 'error')
}
}
},
}
+2
View File
@@ -315,6 +315,8 @@ export function shouldShowErrorToast(error) {
// Don't show toast for user cancellations
if (error instanceof AuthCancelledError) return false
if (error.name === 'AbortError') return false
// Don't show toast for 401/403 errors - the auth iframe will handle these
if (error instanceof ApiError && (error.status === 401 || error.status === 403)) return false
return true
}
+3 -12
View File
@@ -5,8 +5,8 @@ class AwaitableWebSocket extends WebSocket {
#opened = false
constructor(resolve, reject, url, protocols, binaryType) {
// Support relative URLs even on old browsers that don't
super(new URL(url, location.href.replace(/^http/, 'ws')), protocols)
// Support relative URLs even on old browsers that don't natively support them
super(new URL(url, document.baseURI.replace(/^http/, 'ws')), protocols)
this.binaryType = binaryType || 'blob'
this.onopen = () => {
this.#opened = true
@@ -51,21 +51,12 @@ class AwaitableWebSocket extends WebSocket {
console.error("WebSocket received binary data, expected JSON string", data)
throw new Error("WebSocket received binary data, expected JSON string")
}
let parsed
try {
parsed = JSON.parse(data)
return JSON.parse(data)
} catch (err) {
console.error("Failed to parse JSON from WebSocket message", data, err)
throw new Error("Failed to parse JSON from WebSocket message")
}
// Wrap in response-like object with ok based on status field
// Status 2xx = ok, 4xx/5xx = not ok, no status = ok (normal response)
const status = parsed.status || 200
return {
ok: status >= 200 && status < 300,
status,
data: parsed,
}
}
send_json(data) {
+16 -15
View File
@@ -23,28 +23,28 @@ export async function register(resetToken = null, displayName = null, onstartreg
const res = await ws.receive_json()
// Handle auth errors (401/403) with iframe
if ((res.status === 401 || res.status === 403) && res.data.auth?.iframe) {
if ((res.status === 401 || res.status === 403) && res.auth?.iframe) {
ws.close()
await showAuthIframe(res.data.auth.iframe)
await showAuthIframe(res.auth.iframe)
continue
}
// Handle other errors
if (!res.ok) {
throw new Error(res.data.detail || `Registration failed: ${res.status}`)
// Handle other errors (status field present means error)
if (res.status) {
throw new Error(res.detail || `Registration failed: ${res.status}`)
}
// Notify caller that we're about to show the browser prompt
if (onstartreg) onstartreg()
const registrationResponse = await startRegistration({ optionsJSON: res.data })
const registrationResponse = await startRegistration({ optionsJSON: res })
ws.send_json(registrationResponse)
const result = await ws.receive_json()
if (!result.ok) {
throw new Error(result.data.detail || `Registration failed: ${result.status}`)
if (result.status) {
throw new Error(result.detail || `Registration failed: ${result.status}`)
}
return result.data
return result
} catch (error) {
ws.close()
console.error('Registration error:', error)
@@ -58,18 +58,19 @@ export async function authenticate() {
const ws = await aWebSocket(await makeUrl('/auth/ws/authenticate'))
try {
const res = await ws.receive_json()
if (!res.ok) {
throw new Error(res.data.detail || `Authentication failed: ${res.status}`)
// status field present means error
if (res.status) {
throw new Error(res.detail || `Authentication failed: ${res.status}`)
}
const authResponse = await startAuthentication({ optionsJSON: res.data })
const authResponse = await startAuthentication({ optionsJSON: res })
ws.send_json(authResponse)
const result = await ws.receive_json()
if (!result.ok) {
throw new Error(result.data.detail || `Authentication failed: ${result.status}`)
if (result.status) {
throw new Error(result.detail || `Authentication failed: ${result.status}`)
}
return result.data
return result
} catch (error) {
console.error('Authentication error:', error)
throw Error(error.name === "NotAllowedError" ? 'Passkey authentication cancelled' : error.message)