From 24bd57079513c749686fb827550284c433cbc2d0 Mon Sep 17 00:00:00 2001 From: JBB0807 <104856796+JBB0807@users.noreply.github.com> Date: Tue, 29 Apr 2025 12:01:10 -0700 Subject: [PATCH] added complete api functionality --- assignment-db-service/DockerfileDEV | 2 +- assignment-db-service/app.js | 137 +++++++++++------- assignment-db-service/dev.env | 4 +- assignment-db-service/prisma/schema.prisma | 22 +-- assignment-service/.env | 4 +- assignment-service/dev.env | 6 +- assignment-service/routes/InstructorRouter.js | 56 +++++-- assignment-service/server.js | 28 ++++ auth-service/dev.env | 2 +- auth-service/routes/auth.js | 46 +++--- auth-service/server.js | 2 +- compose.yaml | 2 +- user-db-service/routes/InstructorRouter.js | 1 - 13 files changed, 205 insertions(+), 107 deletions(-) diff --git a/assignment-db-service/DockerfileDEV b/assignment-db-service/DockerfileDEV index 200df1a..a279eb5 100644 --- a/assignment-db-service/DockerfileDEV +++ b/assignment-db-service/DockerfileDEV @@ -20,7 +20,7 @@ COPY package*.json ./ RUN npm install && npx prisma generate # Rebuild bcrypt specifically (optional if clean install is guaranteed) -RUN npm rebuild bcrypt --build-from-source +# RUN npm rebuild bcrypt --build-from-source # Expose the application port EXPOSE 3200 diff --git a/assignment-db-service/app.js b/assignment-db-service/app.js index dd79ada..115c256 100644 --- a/assignment-db-service/app.js +++ b/assignment-db-service/app.js @@ -1,6 +1,6 @@ -const express = require('express'); -const { PrismaClient } = require('@prisma/client'); -const bcrypt = require('bcrypt'); +const express = require("express"); +const { PrismaClient } = require("@prisma/client"); +const bcrypt = require("bcrypt"); const app = express(); const prisma = new PrismaClient(); @@ -10,117 +10,150 @@ const port = process.env.NODE_PORT || 3000; app.use(express.json()); app.use(express.urlencoded({ extended: true })); +//function to conver req.body to assignment +function convertToAssignment(req) { + const { + campid, + programid, + studentname, + snakegameid, + originalfile, + editablefile, + assignmenturl, + password, + instructorid + } = req.body; + + // const hashedPassword = await bcrypt.hash(Password, 10); + return { + campid: campid, + programid: programid, + studentname: studentname, + snakegameid: snakegameid, + originalfile: originalfile, + editablefile: editablefile, + assignmenturl: assignmenturl, + // passwordhash: hashedpassword, + passwordhash: password, + instructorid: instructorid, + }; + } + // Create Assignment -app.post('/assignments', async (req, res) => { +app.post("/assignments", async (req, res) => { try { - const { - CampID, - ProgramID, - StudentName, - SnakeGameId, - OriginalFile, - EditableFile, - AssignmentUrl, - Password, - InstructorID, - } = req.body; + console.log("Request body:", req.body); - const hashedPassword = await bcrypt.hash(Password, 10); + // const { + // campid, + // programid, + // studentname, + // snakegameid, + // originalfile, + // editablefile, + // assignmenturl, + // password, + // instructorid + // } = req.body; - const newAssignment = await prisma.assignment.create({ + // const hashedPassword = await bcrypt.hash(Password, 10); + const newAssignment = await prisma.assignments.create({ data: { - CampID, - ProgramID, - StudentName, - SnakeGameId, - OriginalFile, - EditableFile, - AssignmentUrl, - PasswordHash: hashedPassword, - InstructorID, + ...convertToAssignment(req) }, }); - res.json({ message: 'Assignment created successfully', assignment: newAssignment }); + console.log("Assignment created successfully:", newAssignment); + + res.json({ + message: "Assignment created successfully", + assignment: newAssignment, + }); } catch (err) { - console.error('Error creating assignment:', err.message); + console.error("Error creating assignment:", err.message); res.status(500).json({ error: err.message }); } }); // Get Assignments by InstructorID -app.get('/assignments/instructor/:instructorId', async (req, res) => { +app.get("/assignments/instructor/:instructorId", async (req, res) => { try { const { instructorId } = req.params; - - const assignments = await prisma.assignment.findMany({ - where: { InstructorID: parseInt(instructorId) }, + console.log("InstructorID:", instructorId); + const assignments = await prisma.assignments.findMany({ + where: { instructorid: parseInt(instructorId) }, }); if (assignments.length === 0) { - return res.status(404).json({ message: 'No assignments found for this instructor' }); + return res + .status(404) + .json({ message: "No assignments found for this instructor" }); } res.json(assignments); } catch (err) { - console.error('Error fetching assignments:', err.message); + console.error("Error fetching assignments:", err.message); res.status(500).json({ error: err.message }); } }); // Read Assignment -app.get('/assignments/:id', async (req, res) => { +app.get("/assignments/:id", async (req, res) => { try { - const assignment = await prisma.assignment.findUnique({ - where: { AssignmentID: parseInt(req.params.id) }, + const assignment = await prisma.assignments.findUnique({ + where: { assignmentid: parseInt(req.params.id) }, }); if (!assignment) { - return res.status(404).json({ message: 'Assignment not found' }); + return res.status(404).json({ message: "Assignment not found" }); } res.json(assignment); } catch (err) { - console.error('Error fetching assignment:', err.message); + console.error("Error fetching assignment:", err.message); res.status(500).json({ error: err.message }); } }); // Update Assignment -app.put('/assignments/:id', async (req, res) => { +app.put("/assignments/:id", async (req, res) => { try { const { id } = req.params; const data = req.body; - if (data.Password) { - data.PasswordHash = await bcrypt.hash(data.Password, 10); - delete data.Password; + if (data.password) { + // data.passwordhash = await bcrypt.hash(data.Password, 10); + data.passwordhash = data.password; + delete data.password; } - const updatedAssignment = await prisma.assignment.update({ - where: { AssignmentID: parseInt(id) }, + const updatedAssignment = await prisma.assignments.update({ + where: { assignmentid: parseInt(id) }, data, }); - res.json({ message: 'Assignment updated successfully', assignment: updatedAssignment }); + res.json({ + message: "Assignment updated successfully", + assignment: updatedAssignment, + }); } catch (err) { - console.error('Error updating assignment:', err.message); + console.error("Error updating assignment:", err.message); res.status(500).json({ error: err.message }); } }); // Delete Assignment -app.delete('/assignments/:id', async (req, res) => { +app.delete("/assignments/:id", async (req, res) => { try { const { id } = req.params; - await prisma.assignment.delete({ - where: { AssignmentID: parseInt(id) }, + await prisma.assignments.delete({ + where: { assignmentid: parseInt(id) }, }); - res.json({ message: 'Assignment deleted successfully' }); + res.json({ message: "Assignment deleted successfully" }); } catch (err) { - console.error('Error deleting assignment:', err.message); + console.error("Error deleting assignment:", err.message); res.status(500).json({ error: err.message }); } }); diff --git a/assignment-db-service/dev.env b/assignment-db-service/dev.env index 9394892..1e00c54 100644 --- a/assignment-db-service/dev.env +++ b/assignment-db-service/dev.env @@ -5,8 +5,8 @@ # See the documentation for all the connection string options: https://pris.ly/d/connection-strings #use this when testing local, remmber to run the proxy command -DATABASE_URL="postgresql://postgres:wly9H8gjjmxYfg1@localhost:15432/postgres?schema=public" +DATABASE_URL="postgresql://postgres:wly9H8gjjmxYfg1@host.docker.internal:15432/postgres?schema=public" # DATABASE_URL="postgres://postgres:wly9H8gjjmxYfg1@bytecamp-db.flycast:5432?sslmode=disable" # DATABASE_URL=postgres://snakebyte:zVB7lgOiKr89dq6@localhost:5432/snakebyte?sslmode=disable -NODE_PORT=3000 +NODE_PORT=3200 diff --git a/assignment-db-service/prisma/schema.prisma b/assignment-db-service/prisma/schema.prisma index 76cb6b3..0a18c40 100644 --- a/assignment-db-service/prisma/schema.prisma +++ b/assignment-db-service/prisma/schema.prisma @@ -8,15 +8,15 @@ datasource db { url = env("DATABASE_URL") } -model Assignment { - AssignmentID Int @id @default(autoincrement()) - CampID Int? - ProgramID Int? - StudentName String - SnakeGameId String? - OriginalFile String? - EditableFile String? - AssignmentUrl String? - PasswordHash String // store bcrypt hash - InstructorID Int? +model assignments { + assignmentid Int @id @default(autoincrement()) + campid Int? + programid Int? + studentname String? + snakegameid String? + originalfile String? + editablefile String? + assignmenturl String? + passwordhash String? // store bcrypt hash + instructorid Int? } diff --git a/assignment-service/.env b/assignment-service/.env index c8a05a6..b948690 100644 --- a/assignment-service/.env +++ b/assignment-service/.env @@ -1,2 +1,2 @@ -#DB_ASSIGNMENT_SERVICE_URL = "http://localhost:3000/" -DB_ASSIGNMENT_SERVICE_URL = "http://db-assignment-service.internal:3000/" +#DB_ASSIGNMENT_SERVICE_URL = "http://localhost:3000" +DB_ASSIGNMENT_SERVICE_URL = "http://db-assignment-service.internal:3000" diff --git a/assignment-service/dev.env b/assignment-service/dev.env index fa4a342..c457dfa 100644 --- a/assignment-service/dev.env +++ b/assignment-service/dev.env @@ -1,3 +1,5 @@ -DB_ASSIGNMENT_SERVICE_URL="http://localhost:3000/" -# DB_ASSIGNMENT_SERVICE_URL="http://db-assignment-service.internal:3000/" +#DB_ASSIGNMENT_SERVICE_URL="http://localhost:3000" +DB_ASSIGNMENT_SERVICE_URL="http://js-assignment-db-service:3200" +AUTH_SESSION_KEY="f3f4d8e6b17a4b3abdc8e9a2c0457aaf91c0d5f6e3b7a9c8df624bd71ea35f42" +ACCEPTED_ORIGINS=http://localhost:3000,http://localhost:8081,http://localhost:3001,http://localhost:5173 PORT=8082 \ No newline at end of file diff --git a/assignment-service/routes/InstructorRouter.js b/assignment-service/routes/InstructorRouter.js index 790e9da..c3a6d01 100644 --- a/assignment-service/routes/InstructorRouter.js +++ b/assignment-service/routes/InstructorRouter.js @@ -2,31 +2,61 @@ const intructorRouter = require("express").Router(); const passport = require("passport"); const axios = require("axios"); -const { DB_ASSIGNMENT_SERVICE_URL } = process.env.DB_ASSIGNMENT_SERVICE_URL || "http://localhost:3000"; +const DB_ASSIGNMENT_SERVICE_URL = process.env.DB_ASSIGNMENT_SERVICE_URL || "http://localhost:3000"; +console.log("DB_ASSIGNMENT_SERVICE_URL:", DB_ASSIGNMENT_SERVICE_URL); // This endpoint is for instructors to create a new assignment -intructorRouter.post("/create", passport.authenticate("jwt", { session: false }), async (req, res) => { +intructorRouter.post("/create", + // passport.authenticate("jwt", { session: false }), + async (req, res) => { try { + console.log("Creating a new assignment with data:", req.body); const response = await axios.post(`${DB_ASSIGNMENT_SERVICE_URL}/assignments`, req.body); + console.log("Response from DB_ASSIGNMENT_SERVICE_URL:", response.data); res.status(response.status).json(response.data); } catch (error) { + console.error("Error creating assignment:", error.message); + res.status(error.response?.status || 500).json({ error: error.message }); + } +}); + +// This endpoint is for instructors to get details of a specific assignment +intructorRouter.get("/details/:id", async (req, res) => { + try { + const assignmentId = req.params.id; + console.log("Fetching details for assignmentId:", assignmentId); + const response = await axios.get(`${DB_ASSIGNMENT_SERVICE_URL}/assignments/${assignmentId}`); + console.log("Response from DB_ASSIGNMENT_SERVICE_URL:", response.data); + res.status(response.status).json(response.data); + } catch (error) { + console.error("Error fetching assignment details:", error.message); res.status(error.response?.status || 500).json({ error: error.message }); } }); // This endpoint is for instructors to get a list of assignments they have created -intructorRouter.get("/list", passport.authenticate("jwt", { session: false }), async (req, res) => { - try { - const instructorId = req.user.id; // Assuming req.user contains the authenticated user - const response = await axios.get(`${DB_ASSIGNMENT_SERVICE_URL}/assignments/instructor/${instructorId}`); - res.status(response.status).json(response.data); - } catch (error) { - res.status(error.response?.status || 500).json({ error: error.message }); - } +intructorRouter.get("/list/:id", async (req, res) => { + // if (req.isAuthenticated()) { + try { + const instructorId = req.params.id; + console.log("Fetching assignments for instructorId:", instructorId); + // const instructorId = req.user.userid; // Assuming req.user contains the authenticated user + const response = await axios.get(`${DB_ASSIGNMENT_SERVICE_URL}/assignments/instructor/${instructorId}`); + console.log("Response from DB_ASSIGNMENT_SERVICE_URL:", response.data); + res.status(response.status).json(response.data); + } catch (error) { + res.status(error.response?.status || 500).json({ error: error.message }); + } + // } else { + // return res.status(401).json({ error: "Not authenticated" }); + // } + }); // This endpoint is for instructors to update an assignment -intructorRouter.put("/update/:id", passport.authenticate("jwt", { session: false }), async (req, res) => { +intructorRouter.put("/update/:id", + // passport.authenticate("jwt", { session: false }), + async (req, res) => { try { const assignmentId = req.params.id; const response = await axios.put(`${DB_ASSIGNMENT_SERVICE_URL}/assignments/${assignmentId}`, req.body); @@ -37,7 +67,9 @@ intructorRouter.put("/update/:id", passport.authenticate("jwt", { session: false }); // This endpoint is for instructors to delete an assignment -intructorRouter.delete("/delete/:id", passport.authenticate("jwt", { session: false }), async (req, res) => { +intructorRouter.delete("/delete/:id", + // passport.authenticate("jwt", { session: false }), + async (req, res) => { try { const assignmentId = req.params.id; const response = await axios.delete(`${DB_ASSIGNMENT_SERVICE_URL}/assignments/${assignmentId}`); diff --git a/assignment-service/server.js b/assignment-service/server.js index ef05abc..bcad1fc 100644 --- a/assignment-service/server.js +++ b/assignment-service/server.js @@ -1,10 +1,38 @@ require('dotenv').config(); +const cors = require("cors"); +const passport = require("passport"); +const session = require("express-session"); const express = require("express"); const instructorRouter = require("./routes/InstructorRouter"); const studentRouter = require("./routes/StudentRouter"); const app = express(); +app.use(express.json()); +app.use(express.urlencoded({ extended: true })); + + +// app.use( +// session({ +// secret: process.env.AUTH_SESSION_KEY, +// resave: false, +// saveUninitialized: false, +// cookie: { +// maxAge: 24 * 60 * 60 * 1000, // 1 day +// }, +// }) +// ); + +// app.use(passport.initialize()); +// app.use(passport.session()); + +// app.use( +// cors({ +// origin: process.env.ACCEPTED_ORIGINS.split(","), +// methods: ["GET", "POST"], +// credentials: true, +// }) +// ) app.use("/instructor", instructorRouter); app.use("/student", studentRouter); diff --git a/auth-service/dev.env b/auth-service/dev.env index 65e6d20..794749f 100644 --- a/auth-service/dev.env +++ b/auth-service/dev.env @@ -2,7 +2,7 @@ GOOGLE_CLIENT_ID="485880105639-1in8tvb6ondnn198rasuj2d8ank06ntp.apps.googleuserc GOOGLE_CLIENT_SECRET="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" GOOGLE_CALLBACK_URL="http://localhost:8080/auth/google/callback" LOGIN_REDIRECT_URL="http://localhost:5173/" -ACCEPTED_ORIGINS=http://localhost:3000,http://localhost:8081,http://localhost:3001,http://localhost:5137 +ACCEPTED_ORIGINS=http://localhost:3000,http://localhost:8081,http://localhost:3001,http://localhost:5173 DB_USER_SERVICE_URL="http://js-user-db-service:3100/" AUTH_SESSION_KEY="f3f4d8e6b17a4b3abdc8e9a2c0457aaf91c0d5f6e3b7a9c8df624bd71ea35f42" PORT=8080 \ No newline at end of file diff --git a/auth-service/routes/auth.js b/auth-service/routes/auth.js index 4e87d0b..782d09c 100644 --- a/auth-service/routes/auth.js +++ b/auth-service/routes/auth.js @@ -5,35 +5,39 @@ const axios = require("axios"); router.get( "/google/callback", passport.authenticate("google", { - successRedirect: "/auth/login", + successRedirect: "/auth/google/login", failureRedirect: "/auth/login/failed", }) ); -router.get('/current_user', (req, res) => { +router.get("/current_user", (req, res) => { if (req.isAuthenticated()) { + console.log("Authenticated user:", req.user); res.json(req.user); } else { - res.status(401).json({ error: 'Not authenticated' }); + console.log("User not authenticated"); + res.status(401).json({ error: "Not authenticated" }); } }); -router.get("/login", (req, res) => { +router.get("/google/login", (req, res) => { if (req.user) { - - console.log(`${process.env.DB_USER_SERVICE_URL}instructor/register-user`) - axios.post(`${process.env.DB_USER_SERVICE_URL}instructor/register-user`, { - user: req.user, - }) - .then(response => { - console.log("User registration response:", response.data); - res.redirect(process.env.LOGIN_REDIRECT_URL); - }) - .catch(error => { - console.error("Error registering user:", error.message); - res.status(500).json({ error: true, message: "User login failed" }); - }); - + console.log(`${process.env.DB_USER_SERVICE_URL}instructor/register-user`); + axios + .post(`${process.env.DB_USER_SERVICE_URL}instructor/register-user`, { + user: req.user, + }) + .then((response) => { + req.user.userId = response.data.user.userid; + console.log("User ID:", response.data.user.userid); + req.user.role = "instructor"; + console.log("User registration response:", response.data); + res.redirect(process.env.LOGIN_REDIRECT_URL); + }) + .catch((error) => { + console.error("Error registering user:", error.message); + res.status(500).json({ error: true, message: "User login failed" }); + }); } else { res.status(403).json({ error: true, message: "Not Authorized" }); } @@ -49,8 +53,8 @@ router.get("/login/failed", (req, res) => { router.get("/google", passport.authenticate("google", ["profile", "email"])); router.get("/logout", (req, res) => { - req.logOut(); - res.redirect(process.env.LOGIN_REDIRECT_URL); + req.logOut(); + res.redirect(process.env.LOGIN_REDIRECT_URL); }); -module.exports = router; \ No newline at end of file +module.exports = router; diff --git a/auth-service/server.js b/auth-service/server.js index 6c20d5e..8e92dce 100644 --- a/auth-service/server.js +++ b/auth-service/server.js @@ -26,7 +26,7 @@ app.use(passport.session()); app.use( cors({ origin: process.env.ACCEPTED_ORIGINS.split(","), - methods: "GET", + methods: ["GET", "POST"], credentials: true, }) ) diff --git a/compose.yaml b/compose.yaml index 436b058..99c6a2d 100644 --- a/compose.yaml +++ b/compose.yaml @@ -9,7 +9,7 @@ services: restart: unless-stopped init: true ports: - - "3000:3000" # Expose port to the same host + - "3200:3200" # Expose port to the same host env_file: - ./assignment-db-service/dev.env networks: diff --git a/user-db-service/routes/InstructorRouter.js b/user-db-service/routes/InstructorRouter.js index 4f81efd..0b4c0a5 100644 --- a/user-db-service/routes/InstructorRouter.js +++ b/user-db-service/routes/InstructorRouter.js @@ -38,7 +38,6 @@ instructorRouter.post("/register-user", async (req, res) => { }, }); console.log("New user created:", newUser); - res.json({ message: "User added successfully", user: newUser }); } else { console.log("User already exists:", user);