Spaces:
Running
Running
Isitha Tennakoon
commited on
Commit
·
c5ac4b3
1
Parent(s):
331ca47
added documentation to keygen code
Browse files
keygenServer/README.md
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
This is the code for API key Generation
|
2 |
+
|
3 |
+
## Client
|
4 |
+
|
5 |
+
This is the interface a user goes to for requesting an API key.
|
6 |
+
|
7 |
+
The client asks the server to generate a new API key. Only the client website
|
8 |
+
can request new keys.
|
9 |
+
|
10 |
+
Login is handled through google auth. Keys are associated with email addresses.
|
11 |
+
|
12 |
+
## Server
|
13 |
+
|
14 |
+
Server handles requests for new keys. It also exposes and endpoint for verifying
|
15 |
+
that a key exists. Currently it doesn't do anything more can check existance of
|
16 |
+
keys, but we will be fixing that soon.
|
17 |
+
|
18 |
+
|
keygenServer/client/Dockerfile
CHANGED
@@ -1,4 +1,8 @@
|
|
|
|
|
|
1 |
# Build stage
|
|
|
|
|
2 |
FROM node:20-alpine AS builder
|
3 |
|
4 |
WORKDIR /app
|
@@ -43,4 +47,4 @@ RUN yarn install --production --frozen-lockfile
|
|
43 |
EXPOSE 3000
|
44 |
|
45 |
# Start the application
|
46 |
-
CMD ["yarn", "start"]
|
|
|
1 |
+
# We deployed to Vercel so this Dockerfile isn't actually being used
|
2 |
+
|
3 |
# Build stage
|
4 |
+
|
5 |
+
|
6 |
FROM node:20-alpine AS builder
|
7 |
|
8 |
WORKDIR /app
|
|
|
47 |
EXPOSE 3000
|
48 |
|
49 |
# Start the application
|
50 |
+
CMD ["yarn", "start"]
|
keygenServer/client/app/main/page.tsx
CHANGED
@@ -1,4 +1,7 @@
|
|
1 |
'use client';
|
|
|
|
|
|
|
2 |
import { useEffect, useState } from 'react';
|
3 |
import { useRouter } from 'next/navigation';
|
4 |
|
@@ -36,6 +39,7 @@ export default function MainPage() {
|
|
36 |
router.push('/');
|
37 |
};
|
38 |
|
|
|
39 |
const generateApiKey = async () => {
|
40 |
try {
|
41 |
const response = await fetch('https://mcp-hackathon-tu1u.onrender.com/api/addKey', {
|
@@ -205,4 +209,4 @@ export default function MainPage() {
|
|
205 |
</div>
|
206 |
</div>
|
207 |
);
|
208 |
-
}
|
|
|
1 |
'use client';
|
2 |
+
|
3 |
+
// This is the homepage of the app. Where you request a new key.
|
4 |
+
|
5 |
import { useEffect, useState } from 'react';
|
6 |
import { useRouter } from 'next/navigation';
|
7 |
|
|
|
39 |
router.push('/');
|
40 |
};
|
41 |
|
42 |
+
// Call the server to obtain a key
|
43 |
const generateApiKey = async () => {
|
44 |
try {
|
45 |
const response = await fetch('https://mcp-hackathon-tu1u.onrender.com/api/addKey', {
|
|
|
209 |
</div>
|
210 |
</div>
|
211 |
);
|
212 |
+
}
|
keygenServer/client/app/page.tsx
CHANGED
@@ -1,7 +1,8 @@
|
|
1 |
'use client';
|
2 |
-
|
3 |
-
//
|
4 |
-
|
|
|
5 |
import { useRouter } from 'next/navigation';
|
6 |
import { useCallback } from 'react';
|
7 |
|
|
|
1 |
'use client';
|
2 |
+
|
3 |
+
// This is the login screen for the client website.
|
4 |
+
|
5 |
+
|
6 |
import { useRouter } from 'next/navigation';
|
7 |
import { useCallback } from 'react';
|
8 |
|
keygenServer/server/prisma/schema.prisma
CHANGED
@@ -1,8 +1,4 @@
|
|
1 |
-
//
|
2 |
-
// learn more about it in the docs: https://pris.ly/d/prisma-schema
|
3 |
-
|
4 |
-
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
|
5 |
-
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
|
6 |
|
7 |
generator client {
|
8 |
provider = "prisma-client-js"
|
|
|
1 |
+
// Prisma Schema for API key DB
|
|
|
|
|
|
|
|
|
2 |
|
3 |
generator client {
|
4 |
provider = "prisma-client-js"
|
keygenServer/server/prisma_client.ts
CHANGED
@@ -1,5 +1,12 @@
|
|
1 |
-
|
2 |
|
3 |
-
|
4 |
|
5 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Setting up prisma lib
|
2 |
|
3 |
+
import { PrismaClient } from '@prisma/client';
|
4 |
|
5 |
+
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
6 |
+
|
7 |
+
export const prisma =
|
8 |
+
globalForPrisma.prisma ?? new PrismaClient();
|
9 |
+
|
10 |
+
if (process.env.NODE_ENV !== 'production') {
|
11 |
+
globalForPrisma.prisma = prisma;
|
12 |
+
}
|
keygenServer/server/server.ts
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
import express, { Request, Response } from 'express';
|
2 |
import cors from 'cors';
|
3 |
import dotenv from 'dotenv';
|
4 |
-
import prisma from './prisma_client';
|
5 |
import crypto from 'crypto';
|
6 |
|
7 |
|
@@ -12,15 +12,17 @@ const port = process.env.PORT || 3001;
|
|
12 |
|
13 |
// Whitelist of allowed client origins
|
14 |
const allowedOrigins = [
|
|
|
15 |
'http://localhost:3000',
|
16 |
-
|
17 |
-
'
|
18 |
];
|
19 |
|
20 |
// Strict CORS configuration for protected routes
|
21 |
const strictCorsOptions = {
|
22 |
origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => {
|
23 |
-
|
|
|
24 |
callback(null, true);
|
25 |
} else {
|
26 |
callback(new Error('Not allowed by CORS'));
|
@@ -33,25 +35,22 @@ const strictCorsOptions = {
|
|
33 |
// Open CORS configuration for public routes
|
34 |
const openCorsOptions = {
|
35 |
origin: '*',
|
36 |
-
methods: ['GET', 'POST'],
|
37 |
credentials: true
|
38 |
};
|
39 |
|
40 |
-
// app.use(cors({
|
41 |
-
// origin: allowedOrigins,
|
42 |
-
// credentials: true,
|
43 |
-
// methods: ['GET', 'POST', 'OPTIONS']
|
44 |
-
// }));
|
45 |
|
46 |
// Middleware
|
47 |
app.use(express.json());
|
48 |
|
49 |
-
|
|
|
|
|
50 |
function generateApiKey(): string {
|
51 |
return crypto.randomBytes(32).toString('hex');
|
52 |
}
|
53 |
|
54 |
-
// Public route
|
55 |
app.post('/api/verifyKey',
|
56 |
cors(openCorsOptions),
|
57 |
async (req: Request, res: Response) => {
|
@@ -63,6 +62,7 @@ app.post('/api/verifyKey',
|
|
63 |
return;
|
64 |
}
|
65 |
|
|
|
66 |
const key = await prisma.key.findFirst({
|
67 |
where: {
|
68 |
apiKey
|
@@ -85,6 +85,8 @@ app.post('/api/verifyKey',
|
|
85 |
);
|
86 |
|
87 |
// Protected route with strict CORS and authentication
|
|
|
|
|
88 |
app.post('/api/addKey',
|
89 |
cors(strictCorsOptions),
|
90 |
async (req: Request, res: Response): Promise<void> => {
|
@@ -98,6 +100,7 @@ app.post('/api/addKey',
|
|
98 |
|
99 |
const apiKey = generateApiKey();
|
100 |
|
|
|
101 |
const newKey = await prisma.key.create({
|
102 |
data: {
|
103 |
email,
|
@@ -118,4 +121,4 @@ app.post('/api/addKey',
|
|
118 |
|
119 |
app.listen(port, () => {
|
120 |
console.log(`Server running on port ${port}`);
|
121 |
-
});
|
|
|
1 |
import express, { Request, Response } from 'express';
|
2 |
import cors from 'cors';
|
3 |
import dotenv from 'dotenv';
|
4 |
+
import { prisma } from './prisma_client';
|
5 |
import crypto from 'crypto';
|
6 |
|
7 |
|
|
|
12 |
|
13 |
// Whitelist of allowed client origins
|
14 |
const allowedOrigins = [
|
15 |
+
// for testing
|
16 |
'http://localhost:3000',
|
17 |
+
// deployed frontend
|
18 |
+
'https://mcp-hackathon.vercel.app'
|
19 |
];
|
20 |
|
21 |
// Strict CORS configuration for protected routes
|
22 |
const strictCorsOptions = {
|
23 |
origin: (origin: string | undefined, callback: (err: Error | null, allow?: boolean) => void) => {
|
24 |
+
// disallows CURL, Postman, etc.
|
25 |
+
if (origin && allowedOrigins.includes(origin)) {
|
26 |
callback(null, true);
|
27 |
} else {
|
28 |
callback(new Error('Not allowed by CORS'));
|
|
|
35 |
// Open CORS configuration for public routes
|
36 |
const openCorsOptions = {
|
37 |
origin: '*',
|
38 |
+
methods: ['GET', 'POST', 'OPTIONS'],
|
39 |
credentials: true
|
40 |
};
|
41 |
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
// Middleware
|
44 |
app.use(express.json());
|
45 |
|
46 |
+
// Generates Key
|
47 |
+
// TODO: add verification that key doesn't exist and add key if needed.
|
48 |
+
// currently relying on sheer probablistic chance :P
|
49 |
function generateApiKey(): string {
|
50 |
return crypto.randomBytes(32).toString('hex');
|
51 |
}
|
52 |
|
53 |
+
// Public route (no CORS restrictions)
|
54 |
app.post('/api/verifyKey',
|
55 |
cors(openCorsOptions),
|
56 |
async (req: Request, res: Response) => {
|
|
|
62 |
return;
|
63 |
}
|
64 |
|
65 |
+
// See if key is in database
|
66 |
const key = await prisma.key.findFirst({
|
67 |
where: {
|
68 |
apiKey
|
|
|
85 |
);
|
86 |
|
87 |
// Protected route with strict CORS and authentication
|
88 |
+
app.options('/api/addKey', cors(strictCorsOptions));
|
89 |
+
app.options('/api/addKey/', cors(strictCorsOptions));
|
90 |
app.post('/api/addKey',
|
91 |
cors(strictCorsOptions),
|
92 |
async (req: Request, res: Response): Promise<void> => {
|
|
|
100 |
|
101 |
const apiKey = generateApiKey();
|
102 |
|
103 |
+
// Add key to database
|
104 |
const newKey = await prisma.key.create({
|
105 |
data: {
|
106 |
email,
|
|
|
121 |
|
122 |
app.listen(port, () => {
|
123 |
console.log(`Server running on port ${port}`);
|
124 |
+
});
|