Spaces:
Running
Running
File size: 3,394 Bytes
e0c5640 ae44544 262b7d6 e0c5640 ae44544 ce3adc9 ae44544 02cd6ee ae44544 02cd6ee ae44544 02cd6ee bec9942 ae44544 429b0fe ae44544 e0c5640 ae44544 02cd6ee e0c5640 02cd6ee e0c5640 02cd6ee e0c5640 ae44544 02cd6ee 429b0fe e398af3 ae44544 e0c5640 02cd6ee e0c5640 ae44544 ce3adc9 ae44544 02cd6ee |
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 ? 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}`);
});
|