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
- // import { auth, googleProvider } from '@/libs/firebase';
3
- // import { signInWithPopup } from 'firebase/auth';
4
- // import { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';
 
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
- // This is your Prisma schema file,
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
- import { PrismaClient } from '@prisma/client'
2
 
3
- const prisma = new PrismaClient()
4
 
5
- export default prisma
 
 
 
 
 
 
 
 
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
- 'https://mcp-hackathon.vercel.app',
17
- 'http://your-production-domain.com'
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
- if (!origin || allowedOrigins.includes(origin)) {
 
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 example (no CORS restrictions)
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
+ });