Spaces:
Running
Running
import express, { Request, Response } from 'express'; | |
import cors from 'cors'; | |
import dotenv from 'dotenv'; | |
import { prisma } from './prisma_client'; | |
import crypto from 'crypto'; | |
dotenv.config(); | |
const app = express(); | |
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 10000; | |
// Whitelist of allowed client origins | |
const allowedOrigins = [ | |
// for testing | |
'http://localhost:3000', | |
// deployed frontend | |
'https://mcp-hackathon.vercel.app' | |
]; | |
// Strict CORS configuration for protected routes | |
const strictCorsOptions = { | |
origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => { | |
// disallows CURL, Postman, etc. | |
if (origin && allowedOrigins.includes(origin)) { | |
callback(null, true); | |
} else { | |
callback(new Error('Not allowed by CORS')); | |
} | |
}, | |
methods: ['GET', 'POST'], | |
credentials: true | |
}; | |
// Open CORS configuration for public routes | |
const openCorsOptions = { | |
origin: '*', | |
methods: ['GET', 'POST', 'OPTIONS'], | |
credentials: true | |
}; | |
// Middleware | |
app.use(express.json()); | |
// Generates Key | |
// TODO: add verification that key doesn't exist and add key if needed. | |
// currently relying on sheer probablistic chance :P | |
function generateApiKey(): string { | |
return crypto.randomBytes(32).toString('hex'); | |
} | |
// Public route (no CORS restrictions) | |
app.post('/api/verifyKey', | |
cors(openCorsOptions), | |
async (req: Request, res: Response) => { | |
try { | |
const { apiKey } = req.body; | |
if (!apiKey) { | |
res.status(400).json({ error: 'API key is required' }); | |
return; | |
} | |
// See if key is in database | |
const key = await prisma.key.findFirst({ | |
where: { | |
apiKey | |
} | |
}); | |
if (!key) { | |
res.status(401).json({ valid: false }); | |
return; | |
} | |
else { | |
res.json({ valid: true }); | |
} | |
} catch (error) { | |
console.error('Error verifying API key:', error); | |
res.status(500).json({ error: 'Failed to verify API key' }); | |
} | |
} | |
); | |
// Protected route with strict CORS and authentication | |
app.options('/api/addKey', cors(strictCorsOptions)); | |
app.options('/api/addKey/', cors(strictCorsOptions)); | |
app.post('/api/addKey', | |
cors(strictCorsOptions), | |
async (req: Request, res: Response): Promise<void> => { | |
try { | |
const { email } = req.body; | |
if (!email) { | |
res.status(400).json({ error: 'Email is required' }); | |
return; | |
} | |
const apiKey = generateApiKey(); | |
// Add key to database | |
const newKey = await prisma.key.create({ | |
data: { | |
email, | |
apiKey, | |
} | |
}); | |
res.json({ | |
message: 'API key generated successfully', | |
apiKey: newKey.apiKey | |
}); | |
} catch (error) { | |
console.error('Error creating API key:', error); | |
res.status(500).json({ error: 'Failed to create API key' }); | |
} | |
} | |
); | |
app.listen(port, '0.0.0.0', () => { | |
console.log(`Server running on port ${port}`); | |
}); | |