Sughan-0077 commited on
Commit
0d8870e
·
1 Parent(s): ddd7f1c

Fix CORS and improved error handling for HF deployment

Browse files
backend/src/server.js CHANGED
@@ -23,13 +23,29 @@ const allowedOrigins = [
23
 
24
  app.use(cors({
25
  origin: (origin, cb) => {
26
- // Allow requests with no origin (nginx proxy, curl, etc.)
27
- if (!origin || allowedOrigins.includes(origin)) return cb(null, true);
28
- cb(new Error('CORS blocked'));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  },
30
  credentials: true,
31
- methods: ['GET','POST','PATCH','PUT','DELETE','OPTIONS'],
32
- allowedHeaders: ['Content-Type','Authorization'],
33
  }));
34
 
35
  const generalLimiter = rateLimit({ windowMs: 15*60*1000, max: 500, standardHeaders: true, legacyHeaders: false });
@@ -49,14 +65,25 @@ app.use('/api/tasks/:id/comments', commentRoutes);
49
  app.use('/api/admin', adminRoutes);
50
 
51
  app.use((req, res) => res.status(404).json({ error: 'Endpoint not found.' }));
 
 
52
  app.use((err, req, res, next) => {
53
- console.error('Unhandled error:', err.message);
 
 
 
 
 
 
 
 
 
54
  res.status(500).json({ error: 'An unexpected error occurred.' });
55
  });
56
 
57
  const PORT = process.env.PORT || 5000;
58
  app.listen(PORT, '127.0.0.1', () =>
59
- console.log(`Taskflow API on port ${PORT} [${process.env.NODE_ENV || 'development'}]`)
60
  );
61
 
62
  module.exports = app;
 
23
 
24
  app.use(cors({
25
  origin: (origin, cb) => {
26
+ // Allow requests with no origin (like mobile apps or curl)
27
+ if (!origin) return cb(null, true);
28
+
29
+ // Allow Hugging Face domains or locally allowed origins
30
+ if (origin.endsWith('.hf.space') || origin.includes('huggingface.co') || allowedOrigins.includes(origin)) {
31
+ return cb(null, true);
32
+ }
33
+
34
+ // In production, be a bit more flexible if we're on HF
35
+ if (process.env.NODE_ENV === 'production' && origin.includes('hf.space')) {
36
+ return cb(null, true);
37
+ }
38
+
39
+ // Allow all in development for easier debugging
40
+ if (process.env.NODE_ENV !== 'production') {
41
+ return cb(null, true);
42
+ }
43
+
44
+ cb(new Error(`CORS blocked for origin: ${origin}`));
45
  },
46
  credentials: true,
47
+ methods: ['GET', 'POST', 'PATCH', 'PUT', 'DELETE', 'OPTIONS'],
48
+ allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
49
  }));
50
 
51
  const generalLimiter = rateLimit({ windowMs: 15*60*1000, max: 500, standardHeaders: true, legacyHeaders: false });
 
65
  app.use('/api/admin', adminRoutes);
66
 
67
  app.use((req, res) => res.status(404).json({ error: 'Endpoint not found.' }));
68
+
69
+ // Global error handler
70
  app.use((err, req, res, next) => {
71
+ console.error('[Global Error Manager]:', err.message || err);
72
+
73
+ // Specific handling for CORS errors to make them more helpful
74
+ if (err.message && err.message.includes('CORS')) {
75
+ return res.status(403).json({
76
+ error: 'Security block: origin not allowed.',
77
+ details: process.env.NODE_ENV === 'production' ? undefined : err.message
78
+ });
79
+ }
80
+
81
  res.status(500).json({ error: 'An unexpected error occurred.' });
82
  });
83
 
84
  const PORT = process.env.PORT || 5000;
85
  app.listen(PORT, '127.0.0.1', () =>
86
+ console.log(`Taskflow API on port ${PORT} [${process.env.NODE_ENV || 'production'}]`)
87
  );
88
 
89
  module.exports = app;
frontend/src/pages/AcceptInvitePage.jsx CHANGED
@@ -61,7 +61,7 @@ export default function AcceptInvitePage() {
61
  type={showPw?'text':'password'} placeholder="Min 8 characters"
62
  value={form.password} onChange={e=>setForm(f=>({...f,password:e.target.value}))}/>
63
  <button type="button" className={styles.pwToggle} onClick={()=>setShowPw(v=>!v)}>
64
- {showPw?<Eye size={15}/>:<Eye size={15}/>}
65
  </button>
66
  </div>
67
  {errors.password && <span className="field-error">{errors.password}</span>}
 
61
  type={showPw?'text':'password'} placeholder="Min 8 characters"
62
  value={form.password} onChange={e=>setForm(f=>({...f,password:e.target.value}))}/>
63
  <button type="button" className={styles.pwToggle} onClick={()=>setShowPw(v=>!v)}>
64
+ {showPw?<EyeOff size={15}/>:<Eye size={15}/>}
65
  </button>
66
  </div>
67
  {errors.password && <span className="field-error">{errors.password}</span>}