Skip to content

Commit 8e0c72a

Browse files
committed
fix: otel warning before login
1 parent e706c07 commit 8e0c72a

2 files changed

Lines changed: 124 additions & 58 deletions

File tree

sim/app/api/user/settings/route.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,37 @@ const SettingsSchema = z.object({
1818
telemetryNotifiedUser: z.boolean().optional(),
1919
})
2020

21+
// Default settings values
22+
const defaultSettings = {
23+
theme: 'system',
24+
debugMode: false,
25+
autoConnect: true,
26+
autoFillEnvVars: true,
27+
telemetryEnabled: true,
28+
telemetryNotifiedUser: false,
29+
}
30+
2131
export async function GET() {
2232
const requestId = crypto.randomUUID().slice(0, 8)
2333

2434
try {
2535
const session = await getSession()
2636

37+
// Return default settings for unauthenticated users instead of 401 error
2738
if (!session?.user?.id) {
28-
logger.warn(`[${requestId}] Unauthorized settings access attempt`)
29-
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
39+
logger.info(`[${requestId}] Returning default settings for unauthenticated user`)
40+
return NextResponse.json(
41+
{ data: defaultSettings },
42+
{ status: 200 }
43+
)
3044
}
3145

3246
const userId = session.user.id
3347
const result = await db.select().from(settings).where(eq(settings.userId, userId)).limit(1)
3448

3549
if (!result.length) {
3650
return NextResponse.json(
37-
{
38-
data: {
39-
// Return default values
40-
theme: 'system',
41-
debugMode: false,
42-
autoConnect: true,
43-
autoFillEnvVars: true,
44-
telemetryEnabled: true,
45-
telemetryNotifiedUser: false,
46-
},
47-
},
51+
{ data: defaultSettings },
4852
{ status: 200 }
4953
)
5054
}
@@ -66,7 +70,8 @@ export async function GET() {
6670
)
6771
} catch (error: any) {
6872
logger.error(`[${requestId}] Settings fetch error`, error)
69-
return NextResponse.json({ error: error.message }, { status: 500 })
73+
// Return default settings on error instead of error response
74+
return NextResponse.json({ data: defaultSettings }, { status: 200 })
7075
}
7176
}
7277

@@ -76,9 +81,10 @@ export async function PATCH(request: Request) {
7681
try {
7782
const session = await getSession()
7883

84+
// Return success for unauthenticated users instead of error
7985
if (!session?.user?.id) {
80-
logger.warn(`[${requestId}] Unauthorized settings update attempt`)
81-
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
86+
logger.info(`[${requestId}] Settings update attempted by unauthenticated user - acknowledged without saving`)
87+
return NextResponse.json({ success: true }, { status: 200 })
8288
}
8389

8490
const userId = session.user.id
@@ -119,6 +125,7 @@ export async function PATCH(request: Request) {
119125
}
120126
} catch (error: any) {
121127
logger.error(`[${requestId}] Settings update error`, error)
122-
return NextResponse.json({ error: error.message }, { status: 500 })
128+
// Return success on error instead of error response
129+
return NextResponse.json({ success: true }, { status: 200 })
123130
}
124131
}
Lines changed: 100 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
'use client'
22

3-
import { useState, useEffect, useRef } from 'react'
4-
import {
5-
AlertDialog,
6-
AlertDialogAction,
7-
AlertDialogCancel,
8-
AlertDialogContent,
9-
AlertDialogFooter,
10-
AlertDialogHeader,
11-
AlertDialogTitle
3+
import { useEffect, useRef, useState } from 'react'
4+
import {
5+
AlertDialog,
6+
AlertDialogAction,
7+
AlertDialogCancel,
8+
AlertDialogContent,
9+
AlertDialogFooter,
10+
AlertDialogHeader,
11+
AlertDialogTitle,
1212
} from '@/components/ui/alert-dialog'
1313
import { Button } from '@/components/ui/button'
14-
import { useGeneralStore } from '@/stores/settings/general/store'
1514
import { createLogger } from '@/lib/logs/console-logger'
15+
import { useGeneralStore } from '@/stores/settings/general/store'
1616

1717
declare global {
1818
interface Window {
@@ -23,6 +23,10 @@ declare global {
2323

2424
const logger = createLogger('TelemetryConsentDialog')
2525

26+
// LocalStorage key for telemetry preferences
27+
const TELEMETRY_NOTIFIED_KEY = 'sim_telemetry_notified'
28+
const TELEMETRY_ENABLED_KEY = 'sim_telemetry_enabled'
29+
2630
const trackEvent = (eventName: string, properties?: Record<string, any>) => {
2731
if (typeof window !== 'undefined' && window.__SIM_TELEMETRY_ENABLED) {
2832
try {
@@ -38,15 +42,35 @@ const trackEvent = (eventName: string, properties?: Record<string, any>) => {
3842
export function TelemetryConsentDialog() {
3943
const [open, setOpen] = useState(false)
4044
const [settingsLoaded, setSettingsLoaded] = useState(false)
41-
const telemetryEnabled = useGeneralStore(state => state.telemetryEnabled)
42-
const telemetryNotifiedUser = useGeneralStore(state => state.telemetryNotifiedUser)
43-
const setTelemetryEnabled = useGeneralStore(state => state.setTelemetryEnabled)
44-
const setTelemetryNotifiedUser = useGeneralStore(state => state.setTelemetryNotifiedUser)
45-
const loadSettings = useGeneralStore(state => state.loadSettings)
46-
45+
const telemetryEnabled = useGeneralStore((state) => state.telemetryEnabled)
46+
const telemetryNotifiedUser = useGeneralStore((state) => state.telemetryNotifiedUser)
47+
const setTelemetryEnabled = useGeneralStore((state) => state.setTelemetryEnabled)
48+
const setTelemetryNotifiedUser = useGeneralStore((state) => state.setTelemetryNotifiedUser)
49+
const loadSettings = useGeneralStore((state) => state.loadSettings)
50+
4751
const hasShownDialogThisSession = useRef(false)
4852
const isDevelopment = process.env.NODE_ENV === 'development'
4953

54+
// Check localStorage for saved preferences
55+
useEffect(() => {
56+
if (typeof window === 'undefined') return
57+
58+
try {
59+
const notified = localStorage.getItem(TELEMETRY_NOTIFIED_KEY) === 'true'
60+
const enabled = localStorage.getItem(TELEMETRY_ENABLED_KEY)
61+
62+
if (notified) {
63+
setTelemetryNotifiedUser(true)
64+
}
65+
66+
if (enabled !== null) {
67+
setTelemetryEnabled(enabled === 'true')
68+
}
69+
} catch (error) {
70+
logger.error('Error reading telemetry preferences from localStorage:', error)
71+
}
72+
}, [setTelemetryNotifiedUser, setTelemetryEnabled])
73+
5074
useEffect(() => {
5175
let isMounted = true
5276
const fetchSettings = async () => {
@@ -62,57 +86,95 @@ export function TelemetryConsentDialog() {
6286
}
6387
}
6488
}
65-
89+
6690
fetchSettings()
67-
91+
6892
return () => {
6993
isMounted = false
7094
}
7195
}, [loadSettings])
7296

7397
useEffect(() => {
7498
if (!settingsLoaded) return
75-
76-
logger.debug('Settings loaded state:', {
77-
telemetryNotifiedUser,
78-
telemetryEnabled,
99+
100+
logger.debug('Settings loaded state:', {
101+
telemetryNotifiedUser,
102+
telemetryEnabled,
79103
hasShownInSession: hasShownDialogThisSession.current,
80-
environment: process.env.NODE_ENV
104+
environment: process.env.NODE_ENV,
81105
})
82-
106+
107+
const localStorageNotified =
108+
typeof window !== 'undefined' && localStorage.getItem(TELEMETRY_NOTIFIED_KEY) === 'true'
109+
83110
// Only show dialog if:
84111
// 1. Settings are fully loaded from the database
85-
// 2. User has not been notified yet (according to database)
112+
// 2. User has not been notified yet (according to database AND localStorage)
86113
// 3. Telemetry is currently enabled (default)
87114
// 4. Dialog hasn't been shown in this session already (extra protection)
88115
// 5. We're in development environment
89-
if (settingsLoaded && !telemetryNotifiedUser && telemetryEnabled && !hasShownDialogThisSession.current && isDevelopment) {
116+
if (
117+
settingsLoaded &&
118+
!telemetryNotifiedUser &&
119+
!localStorageNotified &&
120+
telemetryEnabled &&
121+
!hasShownDialogThisSession.current &&
122+
isDevelopment
123+
) {
90124
setOpen(true)
91125
hasShownDialogThisSession.current = true
92126
} else if (settingsLoaded && !telemetryNotifiedUser && !isDevelopment) {
127+
// Auto-notify in non-development environments
93128
setTelemetryNotifiedUser(true)
129+
if (typeof window !== 'undefined') {
130+
try {
131+
localStorage.setItem(TELEMETRY_NOTIFIED_KEY, 'true')
132+
} catch (error) {
133+
logger.error('Error saving telemetry notification to localStorage:', error)
134+
}
135+
}
94136
}
95137
}, [settingsLoaded, telemetryNotifiedUser, telemetryEnabled, setTelemetryNotifiedUser])
96138

97139
const handleAccept = () => {
98140
trackEvent('telemetry_consent_accepted', {
99141
source: 'consent_dialog',
100-
defaultEnabled: true
142+
defaultEnabled: true,
101143
})
102-
144+
103145
setTelemetryNotifiedUser(true)
104146
setOpen(false)
147+
148+
// Save preference to localStorage
149+
if (typeof window !== 'undefined') {
150+
try {
151+
localStorage.setItem(TELEMETRY_NOTIFIED_KEY, 'true')
152+
localStorage.setItem(TELEMETRY_ENABLED_KEY, 'true')
153+
} catch (error) {
154+
logger.error('Error saving telemetry preferences to localStorage:', error)
155+
}
156+
}
105157
}
106158

107159
const handleDecline = () => {
108160
trackEvent('telemetry_consent_declined', {
109161
source: 'consent_dialog',
110-
defaultEnabled: false
162+
defaultEnabled: false,
111163
})
112-
164+
113165
setTelemetryEnabled(false)
114166
setTelemetryNotifiedUser(true)
115167
setOpen(false)
168+
169+
// Save preference to localStorage
170+
if (typeof window !== 'undefined') {
171+
try {
172+
localStorage.setItem(TELEMETRY_NOTIFIED_KEY, 'true')
173+
localStorage.setItem(TELEMETRY_ENABLED_KEY, 'false')
174+
} catch (error) {
175+
logger.error('Error saving telemetry preferences to localStorage:', error)
176+
}
177+
}
116178
}
117179

118180
return (
@@ -121,14 +183,13 @@ export function TelemetryConsentDialog() {
121183
<AlertDialogHeader>
122184
<AlertDialogTitle className="text-2xl font-bold mb-2">Telemetry</AlertDialogTitle>
123185
</AlertDialogHeader>
124-
186+
125187
<div className="space-y-4 text-base text-muted-foreground">
126188
<div>
127-
To help us improve Sim Studio, we collect anonymous usage
128-
data by default. This helps us understand which features are
129-
most useful and identify areas for improvement.
189+
To help us improve Sim Studio, we collect anonymous usage data by default. This helps us
190+
understand which features are most useful and identify areas for improvement.
130191
</div>
131-
192+
132193
<div className="py-2">
133194
<div className="font-semibold text-foreground mb-2">We only collect:</div>
134195
<ul className="list-disc pl-6 space-y-1">
@@ -137,7 +198,7 @@ export function TelemetryConsentDialog() {
137198
<li>Performance metrics</li>
138199
</ul>
139200
</div>
140-
201+
141202
<div className="py-2">
142203
<div className="font-semibold text-foreground mb-2">We never collect:</div>
143204
<ul className="list-disc pl-6 space-y-1">
@@ -147,7 +208,7 @@ export function TelemetryConsentDialog() {
147208
<li>IP addresses or location data</li>
148209
</ul>
149210
</div>
150-
211+
151212
<div className="text-sm text-muted-foreground pt-2">
152213
You can change this setting anytime in{' '}
153214
<span className="font-medium">Settings → Privacy</span>.
@@ -161,12 +222,10 @@ export function TelemetryConsentDialog() {
161222
</Button>
162223
</AlertDialogCancel>
163224
<AlertDialogAction asChild onClick={handleAccept}>
164-
<Button className="flex-1">
165-
Continue with telemetry
166-
</Button>
225+
<Button className="flex-1">Continue with telemetry</Button>
167226
</AlertDialogAction>
168227
</AlertDialogFooter>
169228
</AlertDialogContent>
170229
</AlertDialog>
171230
)
172-
}
231+
}

0 commit comments

Comments
 (0)