Skip to content

Commit

Permalink
Merge branch 'main' into samuel/PWW-41
Browse files Browse the repository at this point in the history
  • Loading branch information
lolitaroz authored Dec 8, 2024
2 parents fe18203 + c4da8b2 commit 8db189a
Show file tree
Hide file tree
Showing 29 changed files with 1,437 additions and 190 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@
npm-debug.log*
yarn-debug.log*
yarn-error.log*

**/**/.env
768 changes: 680 additions & 88 deletions api/package-lock.json

Large diffs are not rendered by default.

9 changes: 6 additions & 3 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"main": "src/server.ts",
"scripts": {
"build": "tsc",
"start": "nodemon ./dist/server.js",
"dev": "nodemon ./src/server.ts",
"start": "npx ts-node src/server.ts",
"dev": "nodemon --watch 'src/**/*.ts' --exec 'npx ts-node src/server.ts'",
"test": "echo \"Error: no test specified\" && exit 1",
"prettier": "prettier --single-quote --write 'src/**/*.{js,ts}'",
"prettier": "npx prettier --write .",
"format": "prettier --check ."
},
"keywords": [],
Expand All @@ -21,6 +21,7 @@
"express": "^4.21.0",
"mongodb": "^6.9.0",
"mongoose": "^8.4.1",
"sendgrid": "^5.2.3",
"ts-node-dev": "^2.0.0",
"uuid": "^10.0.0"
},
Expand All @@ -30,7 +31,9 @@
"@types/node": "^22.8.1",
"@types/uuid": "^10.0.0",
"body-parser": "^1.20.3",
"nodemon": "^3.1.7",
"prettier": "^3.3.3",
"ts-node": "^10.9.2",
"typescript": "^5.6.2"
}
}
35 changes: 35 additions & 0 deletions api/src/controllers/auth0-errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { Request, Response, NextFunction } from "express";
import {
InvalidTokenError,
UnauthorizedError,
} from "express-oauth2-jwt-bearer";

export const errorHandler = (
error: any,
request: Request,
response: Response,
next: NextFunction,
) => {
console.log("Auth Error");

if (error instanceof InvalidTokenError) {
const message = "Bad credentials";

response.status(error.status).json({ message });

return;
}

if (error instanceof UnauthorizedError) {
const message = "Requires authentication";

response.status(error.status).json({ message });

return;
}

const status = 500;
const message = "Internal Server Error";

response.status(status).json({ message });
};
21 changes: 21 additions & 0 deletions api/src/controllers/auth0-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { auth } from "express-oauth2-jwt-bearer";
import dotenv from "dotenv";
import path from "path";

dotenv.config({ path: path.resolve(__dirname, "../.env") });

const auth0Domain = process.env.AUTH0_DOMAIN;
const auth0Audience = process.env.AUTH0_AUDIENCE;

try {
if (!auth0Domain || !auth0Audience) {
throw new Error("AUTH0_DOMAIN or AUTH0_AUDIENCE is not set");
}
} catch (error) {
console.error(error);
}

export const validateAccessToken = auth({
issuerBaseURL: `https://${auth0Domain}`,
audience: auth0Audience,
});
11 changes: 11 additions & 0 deletions api/src/controllers/auth0-notFound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Request, Response, NextFunction } from "express";

export const notFoundHandler = (
request: Request,
response: Response,
next: NextFunction,
) => {
const message = "Not Found";

response.status(404).json({ message });
};
67 changes: 63 additions & 4 deletions api/src/routes/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ import express from "express";
import mongoose from "mongoose";
import dbConnect from "../config/db";
import sgMail from "@sendgrid/mail";
// import { validateAccessToken } from "../controllers/auth0-middleware";

const router = express.Router();

// TODO: Add auth0 middleware
// router.use(validateAccessToken);

// Call the dbConnect function to connect to MongoDB
dbConnect();

Expand All @@ -19,6 +23,13 @@ const userSchema = new mongoose.Schema({
menteeInfo: [String], // For mentors only
meetingSchedule: [String], // For mentees only
mentorData: String, // For mentees only
meetings: [
{
name: String, // title ??
notes: String,
createdAt: { type: Date, default: Date.now },
},
],
});

const User = mongoose.model("User", userSchema);
Expand All @@ -35,6 +46,7 @@ router.post("/create-user", async (req: any, res: any) => {
menteeInfo,
meetingSchedule,
mentorData,
meetings,
} = req.body;

if (!firstName || !lastName || !username || !email || !role) {
Expand All @@ -52,6 +64,7 @@ router.post("/create-user", async (req: any, res: any) => {
menteeInfo: role === "mentor" ? menteeInfo : undefined,
meetingSchedule: role === "mentee" ? meetingSchedule : undefined,
mentorData: role === "mentee" ? mentorData : undefined,
meetings: meetings || [],
});

try {
Expand All @@ -67,9 +80,15 @@ router.post("/create-user", async (req: any, res: any) => {
// Test route to check if the API is working
router.post("/test", async (req: any, res: any) => {
console.log("Received group data:");
const { name } = req.body;

return res.status(200).json({ name });
let name;
if (req.body.name === undefined) {
name = "empty";
} else {
({ name } = req.body);
}

return res.status(200).json(`Your name is ${name}`);
});

router.post("/send-email", async (req: any, res: any) => {
Expand All @@ -81,14 +100,19 @@ router.post("/send-email", async (req: any, res: any) => {
throw new Error("SendGrid API key or test email is missing");
}

const { email, name } = req.body;
const { email, name, role } = req.body;

sgMail.setApiKey(SENDGRID_API_KEY);

const templateId =
role.toLowerCase().trim() === "mentor"
? "d-1694192e437348e2a0517103acae3f00"
: "d-7e26b82cf8624bafa4077b6ed73b52bf";

await sgMail.send({
to: email,
from: SEND_GRID_TEST_EMAIL,
templateId: "d-7e26b82cf8624bafa4077b6ed73b52bf",
templateId: templateId,
dynamicTemplateData: {
name: name,
},
Expand All @@ -100,4 +124,39 @@ router.post("/send-email", async (req: any, res: any) => {
}
});

// Route to add a meeting
router.post("/add-meeting", async (req, res) => {
const { username, meeting, notes } = req.body;

// Validate required fields
if (!username || !meeting || !notes) {
return res.status(400).json({ message: "Missing required fields" });
}

try {
// Find the user by username
console.log("Searching for user with username:", username);
const user = await User.findOne({ username });

if (!user) {
console.error(`User not found for username: ${username}`);
return res.status(404).json({ message: "User not found" });
}

// Add the meeting to the user's meetings array
user.meetings.push({ name: meeting, notes });

// Save the updated user document
await user.save();

console.log("Meeting added successfully for username:", username);
return res
.status(200)
.json({ message: "Meeting added successfully", user });
} catch (error) {
console.error("Error adding meeting:", error);
return res.status(500).json({ message: "Error adding meeting", error });
}
});

export default router;
34 changes: 18 additions & 16 deletions api/src/routes/workshop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,39 +10,42 @@ import {

const router = express.Router();

// TODO: Add auth0 middleware
// router.use(validateAccessToken);

// Call the dbConnect function to connect to MongoDB
dbConnect();

// Workshop schema definition (name and S3 bucket ID)
const workshopIDSchema = new mongoose.Schema({
name: String,
s3ID: String,
// Workshop schema definition (name (required by user), description (required by user), and S3 bucket ID (not required as user input))
const workshopSchema = new mongoose.Schema({
name: { type: String, required: true },
description: { type: String, required: true },
s3id: { type: String, required: false },
});

const Workshop = mongoose.model("WorkshopID", workshopIDSchema);
const Workshop = mongoose.model("Workshop", workshopSchema);

// Route to create a new workshop
router.post("/create-workshop", async (req: any, res: any) => {
const { name, s3id } = req.body;
const { name, description, s3id } = req.body;

if (!name || !s3id) {
if (!name || !description) {
return res.status(400).json({ message: "Missing required fields" });
}

// Create a new workshop
const newWorkshop = new Workshop({
name,
s3id,
});

try {
// Create a new workshop with
const newWorkshop = new Workshop({ name, description, s3id });
const savedWorkshop = await newWorkshop.save();

// Success:
res.status(201).json({
message: "Workshop created successfully",
WorkshopID: savedWorkshop,
workshop: savedWorkshop,
});
} catch (error) {
res.status(401).json({ message: "Failed to create workshop", error });
console.error("Error saving workshop:", error);
res.status(500).json({ message: "Failed to create workshop", error });
}
});

Expand Down Expand Up @@ -76,4 +79,3 @@ router.get(
// export default router;

export default router;
// NO POPULATE VERSION
17 changes: 8 additions & 9 deletions api/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,23 @@
import dotenv from "dotenv";
import path from "path";

dotenv.config({ path: path.resolve(__dirname, "../.env") });

import express from "express";
import bodyParser from "body-parser";
import connectDB from "./config/db";
import * as routes from "./routes/index";
import path from "path";

var cors = require("cors");

const app = express();
app.use(cors());
app.use(cors({ origin: "http://localhost:3000" })); // Connect to the frontend PORT 3000
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.use("/user", routes.user);
app.use("/workshop", routes.workshop);

connectDB();

app.listen(process.env.PORT || 8000, () =>
console.log(`Server running on port ${process.env.PORT || 8000}`),
);
import * as routes from "./routes/index";
app.use("/user", routes.user);
app.use("/api", routes.workshop); // New workshop route

app.listen(process.env.PORT || 8000, () => console.log("Server running..."));
1 change: 0 additions & 1 deletion app/.env

This file was deleted.

Loading

0 comments on commit 8db189a

Please sign in to comment.