File size: 4,452 Bytes
1e2158c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
/**
 * User ID Utility - Ensures proper user isolation
 * 
 * CRITICAL: Each user (authenticated or guest) gets a unique ID.
 * This ID is used to isolate all user data (files, models, chats, etc.)
 */

import { auth } from '../lib/auth-client';

const GUEST_ID_KEY = 'guestUserId';
const USER_ID_KEY = 'userId';

/**
 * Generate a unique guest ID
 */
function generateGuestId(): string {
  const timestamp = Date.now().toString(36);
  const randomPart = Math.random().toString(36).substring(2, 10);
  return `guest_${timestamp}_${randomPart}`;
}

/**
 * Get or create a guest user ID
 * This ensures guests have persistent, unique IDs
 */
function getOrCreateGuestId(): string {
  let guestId = localStorage.getItem(GUEST_ID_KEY);
  
  if (!guestId) {
    guestId = generateGuestId();
    localStorage.setItem(GUEST_ID_KEY, guestId);
    console.log('๐Ÿ†” Created new guest ID:', guestId);
  }
  
  return guestId;
}

/**
 * Get the current user ID (authenticated or guest)
 * ALWAYS use this function to get user ID for API calls
 */
export async function getUserId(): Promise<string> {
  try {
    // First check auth session
    const { data: { session } } = await auth.getSession();
    
    if (session?.user?.id) {
      // Authenticated user - use their user ID
      localStorage.setItem(USER_ID_KEY, session.user.id);
      return session.user.id;
    }
  } catch (error) {
    console.warn('Could not check auth session:', error);
  }
  
  // Check for stored authenticated user ID
  const storedUserId = localStorage.getItem(USER_ID_KEY);
  if (storedUserId && !storedUserId.startsWith('guest_')) {
    return storedUserId;
  }
  
  // Fallback to guest ID
  return getOrCreateGuestId();
}

/**
 * Synchronous version - uses cached value
 * Prefer getUserId() when possible
 */
export function getUserIdSync(): string {
  // Check for authenticated user ID first
  const storedUserId = localStorage.getItem(USER_ID_KEY);
  if (storedUserId && !storedUserId.startsWith('guest_')) {
    return storedUserId;
  }
  
  // Fallback to guest ID
  return getOrCreateGuestId();
}

/**
 * Clear user data on logout
 */
export function clearUserData(): void {
  const userId = getUserIdSync();
  
  // Clear user-specific localStorage items
  const keysToRemove = [
    `mlResults_${userId}`,
    `hasMLResults_${userId}`,
    `userPreferences_${userId}`,
    `userProfile_${userId}`,
  ];
  
  keysToRemove.forEach(key => localStorage.removeItem(key));
  
  // Clear user-specific sessionStorage
  sessionStorage.removeItem(`mlCharts_${userId}`);
  
  // Remove authenticated user ID but keep guest ID
  localStorage.removeItem(USER_ID_KEY);
  
  console.log('๐Ÿงน Cleared user data for:', userId);
}

/**
 * Check if current user is authenticated
 */
export async function isAuthenticated(): Promise<boolean> {
  try {
    const { data: { session } } = await auth.getSession();
    return !!session?.user;
  } catch {
    return false;
  }
}

/**
 * ๐Ÿ” Get authorization headers for fetch calls
 * Use this for all direct fetch() calls to ensure proper auth
 */
export async function getAuthHeaders(): Promise<Record<string, string>> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  
  try {
    const { data: { session } } = await auth.getSession();
    
    if (session?.access_token) {
      headers['Authorization'] = `Bearer ${session.access_token}`;
      headers['X-User-ID'] = session.user.id;
    } else {
      const guestId = getOrCreateGuestId();
      headers['X-User-ID'] = guestId;
    }
  } catch (error) {
    console.warn('Failed to get auth headers:', error);
    const guestId = getOrCreateGuestId();
    headers['X-User-ID'] = guestId;
  }
  
  return headers;
}

/**
 * Sync version - uses cached token if available
 */
export function getAuthHeadersSync(): Record<string, string> {
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  
  const userId = localStorage.getItem(USER_ID_KEY);
  if (userId && !userId.startsWith('guest_')) {
    headers['X-User-ID'] = userId;
    // Note: For sync, we can't get the JWT token without async call
    // The interceptor in api.ts handles adding the token
  } else {
    const guestId = getOrCreateGuestId();
    headers['X-User-ID'] = guestId;
  }
  
  return headers;
}

export default {
  getUserId,
  getUserIdSync,
  clearUserData,
  isAuthenticated,
  getAuthHeaders,
  getAuthHeadersSync,
};