From a2109e9a5f9a3270478b0887fe5c5717b382a611 Mon Sep 17 00:00:00 2001 From: Jacquilyn F Date: Sat, 26 Apr 2025 14:02:57 -0500 Subject: [PATCH] file structure fixed seeds --- server/seed.ts | 22 ------ server/{routes => src/routes/api}/openai.ts | 2 +- server/{ => src/routes}/index.ts | 2 +- server/src/seeds/seed.ts | 27 ++++++++ server/src/server.ts | 63 +++++++++++------ server/src/utils/auth.ts | 77 ++++++++++++--------- 6 files changed, 114 insertions(+), 79 deletions(-) delete mode 100644 server/seed.ts rename server/{routes => src/routes/api}/openai.ts (97%) rename server/{ => src/routes}/index.ts (89%) create mode 100644 server/src/seeds/seed.ts diff --git a/server/seed.ts b/server/seed.ts deleted file mode 100644 index 646ef66..0000000 --- a/server/seed.ts +++ /dev/null @@ -1,22 +0,0 @@ -import mongoose from "mongoose"; -import dotenv from "dotenv"; -import { User } from "./models/User.ts"; -import { Question } from "./models/Question"; - -dotenv.config(); - -await mongoose.connect(process.env.MONGODB_URI!); - -// Wipe collections -await User.deleteMany({}); -await Question.deleteMany({}); - -// Seed data -await User.create({ username: "playerOne", email: "player@example.com", password: "123456" }); -await Question.insertMany([ - { prompt: "Explain closures in JavaScript", difficulty: "hard" }, - { prompt: "What is a component in React?", difficulty: "easy" } -]); - -console.log("🌱 Seeding complete!"); -mongoose.connection.close(); diff --git a/server/routes/openai.ts b/server/src/routes/api/openai.ts similarity index 97% rename from server/routes/openai.ts rename to server/src/routes/api/openai.ts index 996dc29..1620c22 100644 --- a/server/routes/openai.ts +++ b/server/src/routes/api/openai.ts @@ -1,7 +1,7 @@ import express from 'express'; import type { Request, Response } from 'express'; import { OpenAI } from 'openai'; -import { PromptBuilder } from '../src/utils/PromptBuilder'; +import { PromptBuilder } from '../../utils/PromptBuilder'; import dotenv from 'dotenv'; dotenv.config(); diff --git a/server/index.ts b/server/src/routes/index.ts similarity index 89% rename from server/index.ts rename to server/src/routes/index.ts index 5b143a6..9792e29 100644 --- a/server/index.ts +++ b/server/src/routes/index.ts @@ -1,7 +1,7 @@ import express from 'express'; import dotenv from 'dotenv'; import cors from 'cors'; -import openaiRoutes from './routes/openai'; +import openaiRoutes from './api/openai'; dotenv.config(); diff --git a/server/src/seeds/seed.ts b/server/src/seeds/seed.ts new file mode 100644 index 0000000..339b185 --- /dev/null +++ b/server/src/seeds/seed.ts @@ -0,0 +1,27 @@ +import mongoose from "mongoose"; +import dotenv from "dotenv"; +import User from "../models/User"; +// import { Question } from "../models/Question"; + +dotenv.config(); + +async function seedDatabase() { + await mongoose.connect(process.env.MONGODB_URI!); + + // Wipe collections + await User.deleteMany({}); + + // Seed data + await User.create({ username: "playerOne", email: "player@example.com", password: "123456" }); + // await Question.insertMany([ + // { prompt: "Explain closures in JavaScript", difficulty: "hard" }, + // { prompt: "What is a component in React?", difficulty: "easy" } + // ]); + + console.log("🌱 Seeding complete!"); + mongoose.connection.close(); +} + +seedDatabase().catch((error) => { + console.error("Error seeding database:", error); +}); diff --git a/server/src/server.ts b/server/src/server.ts index 775c255..e527958 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -10,28 +10,54 @@ import typeDefs from './schemas/typeDefs'; import resolvers from './schemas/resolvers'; import { authenticateToken } from './utils/auth'; + +// Extend the Request interface to include the user property +declare global { + namespace Express { + interface Request { + user?: any; // Replace 'any' with the appropriate type for your user object + } + } +} + dotenv.config(); - const startServer = async () => { const app = express(); const PORT = process.env.PORT || 3001; const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY! }); - // Middleware - app.use(cors()); - app.use(express.json()); - app.use(express.static('public')); // serve generated mp3 files - app.use(authenticateToken); + // Create a new instance of an Apollo server with the GraphQL schema + const startApolloServer = async () => { + const server = new ApolloServer({ + typeDefs, + resolvers, + }); - // Apollo Server setup - const server = new ApolloServer({ - typeDefs, - resolvers, - context: ({ req }: { req: Request }) => ({ user: req.user }), - }); + await server.start(); + app.use(express.urlencoded({ extended: false })); + app.use(express.json()); + app.use(express.static('public')); // serve generated mp3 file + app.use('/graphql', expressMiddleware(server as any, + { + context: authenticateToken as any + } + )); + + // if we're in production, serve client/build as static assets + if (process.env.NODE_ENV === 'production') { + app.use(express.static(path.join(dirname, '../client/build'))); + + app.get('*', (_req: Request, res: Response) => { + res.sendFile(path.join(dirname, '../client/dist/index.html')); + }); + } - await server.start(); - server.applyMiddleware({ app, path: '/graphql' }); + // Start the server + app.listen(PORT, () => { + console.log(`✅ Server is running on http://localhost:${PORT}`); + console.log(`✅ GraphQL endpoint is available at http://localhost:${PORT}/graphql`); + }); + }; // TTS Route for Dr. Dan app.post('/api/tts', async (req: Request, res: Response) => { @@ -58,11 +84,4 @@ dotenv.config(); res.send('🎙️ Codezilla server is up!'); }); - // Start the server - app.listen(PORT, () => { - console.log(`✅ Server is running on http://localhost:${PORT}`); - console.log(`✅ GraphQL endpoint is available at http://localhost:${PORT}/graphql`); - }); -}; - -startServer(); \ No newline at end of file +startApolloServer(); \ No newline at end of file diff --git a/server/src/utils/auth.ts b/server/src/utils/auth.ts index 5704091..01ef3ac 100644 --- a/server/src/utils/auth.ts +++ b/server/src/utils/auth.ts @@ -1,56 +1,67 @@ -import type { Request, Response, NextFunction} from 'express'; import jwt from 'jsonwebtoken'; - import dotenv from 'dotenv'; + dotenv.config(); interface JwtPayload { _id: unknown; username: string; email: string; + exp?: number; // Optional expiration field } +export const authMiddleware = ({ req }: { req: any }) => { + const authHeader = req.headers.authorization; -declare global { - namespace Express { - interface Request { - user?: JwtPayload; - } - } -} + if (authHeader) { + const token = authHeader.split(' ')[1]; + const secretKey = process.env.JWT_SECRET_KEY || ''; -export const authenticateToken = (req: Request, res: Response, next: NextFunction) => { - const authHeader = req.headers.authorization || ''; + console.log('Token received:', token); // Log the token - if (!authHeader) { - return res.status(401).json({ error: 'Authorization header is missing' }); - } + try { + const decoded = jwt.decode(token) as JwtPayload | null; - const token = authHeader.split(' ')[1]; - const secretKey = process.env.JWT_SECRET_KEY; + if (!decoded || !decoded.exp) { + throw new Error('Token does not contain expiration date'); + } - if (!secretKey) { - console.error('JWT_SECRET_KEY is not defined in the environment variables'); - return res.status(500).json({ error: 'Internal server error' }); - } + const currentTime = Math.floor(Date.now() / 1000); + if (decoded.exp < currentTime) { + throw new Error('Token has expired'); + } - jwt.verify(token, secretKey, (err, user) => { - if (err) { - console.error('JWT verification failed:', err.message); - return res.status(403).json({ error: 'Invalid or expired token' }); + const user = jwt.verify(token, secretKey) as JwtPayload; + return { user }; + } catch (err) { + console.error('Invalid token:', err); + throw new Error('Invalid token'); } + } - req.user = user as JwtPayload; - next(); - }); + return { user: null }; }; -export const signToken = (username: string, email: string, _id: unknown) => { - const payload = { username, email, _id }; - const secretKey = process.env.JWT_SECRET_KEY; - if (!secretKey) { - throw new Error('JWT_SECRET_KEY is not defined in the environment variables'); +export const authenticateToken = (token: string) => { + const secretKey = process.env.JWT_SECRET_KEY || ''; + + if (!token) { + throw new Error('No token provided'); + } + + try { + const user = jwt.verify(token, secretKey) as JwtPayload; + return user; + } catch (err) { + console.error('Invalid token:', err); + throw new Error('Invalid or expired token'); } +}; - return jwt.sign(payload, secretKey, { expiresIn: '1h' }); +export const signToken = (username: string, email: string, _id: unknown) => { + const payload = { username, email, _id }; + const secretKey = process.env.JWT_SECRET_KEY || ''; + const token = jwt.sign(payload, secretKey, { expiresIn: '1h' }); + console.log('Generated Token:', token); + return token; }; \ No newline at end of file