Spaces:
Sleeping
Sleeping
| 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}`); | |
| }); | |