Spaces:
Running
Running
File size: 3,350 Bytes
e0c5640 ae44544 c5ac4b3 e0c5640 ae44544 e0c5640 ae44544 c5ac4b3 ae44544 c5ac4b3 ae44544 c5ac4b3 ae44544 c5ac4b3 ae44544 e0c5640 ae44544 c5ac4b3 e0c5640 c5ac4b3 e0c5640 c5ac4b3 e0c5640 ae44544 c5ac4b3 e398af3 ae44544 e0c5640 c5ac4b3 e0c5640 ae44544 c5ac4b3 | 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 | 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 || 3001;
// 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, () => {
console.log(`Server running on port ${port}`);
});
|