fix: correct organization context switching to ensure secure session storage when switching away from deleted organizations

This commit is contained in:
Usman Baig
2026-02-22 20:14:18 +01:00
parent acac536590
commit 18d9f59e5d
3 changed files with 6 additions and 42 deletions

View File

@@ -22,6 +22,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
- **Better form experience.** Forms now auto-focus the first field when they open, text inputs enforce character limits with a visible counter when you're close, and the settings page warns you before navigating away with unsaved changes.
- **Tighter name limits.** Site, funnel, and monitor names are now capped at 100 characters instead of 255 — long enough for any real name, short enough to not break the UI.
### Fixed
- **Organization context switch.** Switching away from a deleted organization now stores the session correctly instead of using an insecure fallback.
## [0.10.0-alpha] - 2026-02-21
### Changed

View File

@@ -2,6 +2,7 @@
import { useState, useEffect, useCallback, useRef } from 'react'
import { useRouter, useSearchParams } from 'next/navigation'
import { setSessionAction } from '@/app/actions/auth'
import { useAuth } from '@/lib/auth/context'
import {
deleteOrganization,
@@ -418,7 +419,7 @@ export default function OrganizationSettings() {
// * Switch to personal context explicitly
try {
const { access_token } = await switchContext(null)
localStorage.setItem('token', access_token)
await setSessionAction(access_token)
window.location.href = '/'
} catch (switchErr) {
console.error('Failed to switch to personal context after delete:', switchErr)

View File

@@ -184,46 +184,5 @@ async function apiRequest<T>(
return response.json()
}
// * Legacy axios-style client for compatibility
export function getClient() {
return {
post: async (endpoint: string, body: any) => {
// Handle the case where endpoint might start with /api (remove it if our base client adds it, OR adjust usage)
// Our apiRequest adds /api/v1 prefix.
// If we pass /api/billing/checkout, apiRequest makes it /api/v1/api/billing/checkout -> Wrong.
// We should probably just expose apiRequest directly or wrap it properly.
// Let's adapt the endpoint:
// If endpoint starts with /api/, strip it because apiRequest adds /api/v1
// BUT WAIT: The backend billing endpoint is likely at /api/billing/checkout (not /api/v1/billing/checkout) if I registered it at root group?
// Let's check backend routing.
// In main.go: billingGroup := router.Group("/api/billing") -> so it is at /api/billing/... NOT /api/v1/billing...
// So we need a raw fetch for this, or modify apiRequest to support non-v1 routes.
// For now, let's just implement a simple fetch wrapper that mimics axios
const token = typeof window !== 'undefined' ? localStorage.getItem('token') : null
const headers: any = { 'Content-Type': 'application/json' }
// Although we use cookies, sometimes we might fallback to token if cookies fail?
// Pulse uses cookies primarily now.
const url = `${API_URL}${endpoint}`
const res = await fetch(url, {
method: 'POST',
headers,
body: JSON.stringify(body),
credentials: 'include'
})
if (!res.ok) {
const err = await res.json().catch(() => ({}))
throw new Error(err.error || 'Request failed')
}
return { data: await res.json() }
}
}
}
export const authFetch = apiRequest
export default apiRequest