Pulastya B commited on
Commit
8154116
·
1 Parent(s): 259c45d

Fix Supabase auth on HuggingFace with runtime config injection

Browse files
FRRONTEEEND/App.tsx CHANGED
@@ -21,8 +21,12 @@ const AppContent: React.FC = () => {
21
 
22
  // Handle launch console - redirect to auth if not logged in
23
  const handleLaunchConsole = () => {
24
- // Allow both authenticated and guest users
25
- setView('chat');
 
 
 
 
26
  };
27
 
28
  // Show loading state only briefly
@@ -109,9 +113,9 @@ const AppContent: React.FC = () => {
109
 
110
  <button
111
  onClick={handleLaunchConsole}
112
- className="px-5 py-2 bg-white/5 hover:bg-white/10 border border-white/10 rounded-lg text-sm font-medium transition-all"
113
  >
114
- Launch Console
115
  </button>
116
  </div>
117
  </nav>
 
21
 
22
  // Handle launch console - redirect to auth if not logged in
23
  const handleLaunchConsole = () => {
24
+ if (isAuthenticated) {
25
+ setView('chat');
26
+ } else {
27
+ // Redirect to auth page first
28
+ setView('auth');
29
+ }
30
  };
31
 
32
  // Show loading state only briefly
 
113
 
114
  <button
115
  onClick={handleLaunchConsole}
116
+ className="px-5 py-2 bg-indigo-600 hover:bg-indigo-700 border border-indigo-500/50 rounded-lg text-sm font-medium transition-all text-white"
117
  >
118
+ {isAuthenticated ? 'Launch Console' : 'Get Started'}
119
  </button>
120
  </div>
121
  </nav>
FRRONTEEEND/components/AuthPage.tsx CHANGED
@@ -63,7 +63,7 @@ interface AuthPageProps {
63
  }
64
 
65
  export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
66
- const { signIn, signUp, signInWithGoogle, signInWithGithub } = useAuth();
67
  const [mode, setMode] = useState<'signin' | 'signup'>('signin');
68
  const [currentStep, setCurrentStep] = useState(0);
69
  const [isSubmitting, setIsSubmitting] = useState(false);
@@ -103,6 +103,12 @@ export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
103
 
104
  const handleSignIn = async (e: React.FormEvent) => {
105
  e.preventDefault();
 
 
 
 
 
 
106
  setIsSubmitting(true);
107
  setError(null);
108
 
@@ -114,13 +120,22 @@ export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
114
  onSuccess?.();
115
  }
116
  } catch (err: any) {
117
- setError(err.message || 'An error occurred');
 
 
 
 
118
  } finally {
119
  setIsSubmitting(false);
120
  }
121
  };
122
 
123
  const handleSignUp = async () => {
 
 
 
 
 
124
  setIsSubmitting(true);
125
  setError(null);
126
 
@@ -141,13 +156,22 @@ export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
141
  }, 2000);
142
  }
143
  } catch (err: any) {
144
- setError(err.message || 'An error occurred');
 
 
 
 
145
  } finally {
146
  setIsSubmitting(false);
147
  }
148
  };
149
 
150
  const handleOAuthSignIn = async (provider: 'google' | 'github') => {
 
 
 
 
 
151
  setIsSubmitting(true);
152
  setError(null);
153
 
@@ -157,7 +181,11 @@ export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
157
  setError(error.message);
158
  }
159
  } catch (err: any) {
160
- setError(err.message || 'An error occurred');
 
 
 
 
161
  } finally {
162
  setIsSubmitting(false);
163
  }
 
63
  }
64
 
65
  export const AuthPage: React.FC<AuthPageProps> = ({ onSuccess, onSkip }) => {
66
+ const { signIn, signUp, signInWithGoogle, signInWithGithub, isConfigured } = useAuth();
67
  const [mode, setMode] = useState<'signin' | 'signup'>('signin');
68
  const [currentStep, setCurrentStep] = useState(0);
69
  const [isSubmitting, setIsSubmitting] = useState(false);
 
103
 
104
  const handleSignIn = async (e: React.FormEvent) => {
105
  e.preventDefault();
106
+
107
+ if (!isConfigured) {
108
+ setError('Authentication is not configured. Please contact the administrator.');
109
+ return;
110
+ }
111
+
112
  setIsSubmitting(true);
113
  setError(null);
114
 
 
120
  onSuccess?.();
121
  }
122
  } catch (err: any) {
123
+ if (err.message?.includes('Failed to fetch')) {
124
+ setError('Unable to connect to authentication server. Please try again later.');
125
+ } else {
126
+ setError(err.message || 'An error occurred');
127
+ }
128
  } finally {
129
  setIsSubmitting(false);
130
  }
131
  };
132
 
133
  const handleSignUp = async () => {
134
+ if (!isConfigured) {
135
+ setError('Authentication is not configured. Please contact the administrator.');
136
+ return;
137
+ }
138
+
139
  setIsSubmitting(true);
140
  setError(null);
141
 
 
156
  }, 2000);
157
  }
158
  } catch (err: any) {
159
+ if (err.message?.includes('Failed to fetch')) {
160
+ setError('Unable to connect to authentication server. Please try again later.');
161
+ } else {
162
+ setError(err.message || 'An error occurred');
163
+ }
164
  } finally {
165
  setIsSubmitting(false);
166
  }
167
  };
168
 
169
  const handleOAuthSignIn = async (provider: 'google' | 'github') => {
170
+ if (!isConfigured) {
171
+ setError('Authentication is not configured. Please contact the administrator.');
172
+ return;
173
+ }
174
+
175
  setIsSubmitting(true);
176
  setError(null);
177
 
 
181
  setError(error.message);
182
  }
183
  } catch (err: any) {
184
+ if (err.message?.includes('Failed to fetch')) {
185
+ setError('Unable to connect to authentication server. Please try again later.');
186
+ } else {
187
+ setError(err.message || 'An error occurred');
188
+ }
189
  } finally {
190
  setIsSubmitting(false);
191
  }
FRRONTEEEND/lib/supabase.ts CHANGED
@@ -1,16 +1,49 @@
1
  import { createClient } from '@supabase/supabase-js';
2
 
3
- // Supabase configuration - these will be loaded from environment variables
4
- const supabaseUrl = import.meta.env.VITE_SUPABASE_URL || '';
5
- const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY || '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  // Check if Supabase is configured
8
  export const isSupabaseConfigured = () => {
9
- return !!(supabaseUrl && supabaseAnonKey && supabaseUrl.includes('supabase'));
 
10
  };
11
 
12
- // Create Supabase client
13
- export const supabase = createClient(supabaseUrl || 'https://placeholder.supabase.co', supabaseAnonKey || 'placeholder');
 
 
 
14
 
15
  // Types for our analytics
16
  export interface UsageAnalytics {
 
1
  import { createClient } from '@supabase/supabase-js';
2
 
3
+ // Supabase configuration
4
+ // For HuggingFace Spaces: secrets are injected at runtime via window.__SUPABASE_CONFIG__
5
+ // For local dev: use import.meta.env (Vite build-time variables)
6
+ declare global {
7
+ interface Window {
8
+ __SUPABASE_CONFIG__?: {
9
+ url: string;
10
+ anonKey: string;
11
+ };
12
+ }
13
+ }
14
+
15
+ // Try to get config from runtime injection first (HuggingFace), then fall back to Vite env vars
16
+ const getSupabaseConfig = () => {
17
+ // Check for runtime config (injected by server)
18
+ if (typeof window !== 'undefined' && window.__SUPABASE_CONFIG__) {
19
+ return {
20
+ url: window.__SUPABASE_CONFIG__.url,
21
+ anonKey: window.__SUPABASE_CONFIG__.anonKey
22
+ };
23
+ }
24
+
25
+ // Fall back to Vite build-time env vars
26
+ const url = (typeof import.meta !== 'undefined' && import.meta.env?.VITE_SUPABASE_URL) || '';
27
+ const anonKey = (typeof import.meta !== 'undefined' && import.meta.env?.VITE_SUPABASE_ANON_KEY) || '';
28
+
29
+ return { url, anonKey };
30
+ };
31
+
32
+ const config = getSupabaseConfig();
33
+ const supabaseUrl = config.url;
34
+ const supabaseAnonKey = config.anonKey;
35
 
36
  // Check if Supabase is configured
37
  export const isSupabaseConfigured = () => {
38
+ const cfg = getSupabaseConfig();
39
+ return !!(cfg.url && cfg.anonKey && cfg.url.includes('supabase') && !cfg.url.includes('placeholder'));
40
  };
41
 
42
+ // Create Supabase client (use placeholder if not configured to avoid errors)
43
+ export const supabase = createClient(
44
+ supabaseUrl || 'https://placeholder.supabase.co',
45
+ supabaseAnonKey || 'placeholder-key'
46
+ );
47
 
48
  // Types for our analytics
49
  export interface UsageAnalytics {
src/api/app.py CHANGED
@@ -1132,7 +1132,28 @@ async def serve_frontend(full_path: str):
1132
  # Default to index.html for client-side routing
1133
  index_path = frontend_path / "index.html"
1134
  if index_path.exists():
1135
- return FileResponse(index_path)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1136
 
1137
  # Frontend not built
1138
  raise HTTPException(
 
1132
  # Default to index.html for client-side routing
1133
  index_path = frontend_path / "index.html"
1134
  if index_path.exists():
1135
+ # Inject Supabase config at runtime for HuggingFace Spaces
1136
+ supabase_url = os.getenv("VITE_SUPABASE_URL", "")
1137
+ supabase_anon_key = os.getenv("VITE_SUPABASE_ANON_KEY", "")
1138
+
1139
+ # Read the HTML file
1140
+ html_content = index_path.read_text()
1141
+
1142
+ # Inject the config script before </head>
1143
+ config_script = f"""
1144
+ <script>
1145
+ window.__SUPABASE_CONFIG__ = {{
1146
+ url: "{supabase_url}",
1147
+ anonKey: "{supabase_anon_key}"
1148
+ }};
1149
+ </script>
1150
+ </head>"""
1151
+
1152
+ # Replace </head> with our config + </head>
1153
+ html_content = html_content.replace("</head>", config_script)
1154
+
1155
+ from fastapi.responses import HTMLResponse
1156
+ return HTMLResponse(content=html_content)
1157
 
1158
  # Frontend not built
1159
  raise HTTPException(