Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
2cd433d
setting up with the codealong code
christina-baldwin May 28, 2025
dccb546
setting up fliters and fixing data structure for the flowers example
christina-baldwin May 28, 2025
f980af9
dsipalying endpoints
christina-baldwin May 28, 2025
6e9c2e5
adding routes and modifying data
christina-baldwin May 29, 2025
9a388b8
adding endpoints for get requests
christina-baldwin May 29, 2025
01dcdd6
adding stretch goals: filtering, pagination, error handling, categories
christina-baldwin May 29, 2025
2fdd7aa
fixing names
christina-baldwin May 29, 2025
f7d2b05
adding some dummy data
christina-baldwin May 29, 2025
aed5d75
setting up mongodb
christina-baldwin Jun 2, 2025
37ba143
setting up the schema
christina-baldwin Jun 3, 2025
bec0584
connect schema to model
christina-baldwin Jun 3, 2025
bbfeac8
connecting the server
christina-baldwin Jun 3, 2025
9fbbbfb
filtering
christina-baldwin Jun 3, 2025
67e425f
error handling
christina-baldwin Jun 3, 2025
5eb3668
changing the seeding function and repeated json calls
christina-baldwin Jun 4, 2025
34eb57d
adding post request and adding more to the schema
christina-baldwin Jun 4, 2025
07d8500
setting up the delete thought endpoint
christina-baldwin Jun 4, 2025
4e88d61
setting up a patch endpoint
christina-baldwin Jun 4, 2025
20f9995
removing unneeded notes
christina-baldwin Jun 10, 2025
6e7c257
fixing some typos
christina-baldwin Jun 11, 2025
2d37369
adding a user model
christina-baldwin Jun 11, 2025
14a94ae
fixing
christina-baldwin Jun 11, 2025
7d16c70
setting up authorisation routes
christina-baldwin Jun 11, 2025
2c5f5df
adding middleware
christina-baldwin Jun 11, 2025
37323da
updating server for auth routes and middleware
christina-baldwin Jun 11, 2025
c887bec
routes for liking and unlikeing based on logged in user and authentic…
christina-baldwin Jun 11, 2025
a776933
adding the authenticate import
christina-baldwin Jun 11, 2025
888ca9c
making notes cohesive
christina-baldwin Jun 11, 2025
dcbc1a7
fixing imports and missing packages
christina-baldwin Jun 11, 2025
b85f82f
adding environmental variables
christina-baldwin Jun 11, 2025
dc226b1
fixing the secret key namin issues
christina-baldwin Jun 13, 2025
745449e
fixing the token names
christina-baldwin Jun 13, 2025
1455749
fixing token names
christina-baldwin Jun 13, 2025
230ba89
fix env variable names and remove seeding
christina-baldwin Jun 15, 2025
ffc5332
sreamlining error handling
christina-baldwin Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions data/data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[
{
"id": 1,
"message": "I finally fixed the login bug! 🎉",
"category": "project",
"hearts": 3,
"createdAt": "2024-06-01T10:30:00Z",
"likedBy": ["user123"]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cool feature that you can store user likes on each post 🙌

},
{
"id": 2,
"message": "Meal prepped for the week. Feeling organized!",
"category": "home",
"hearts": 5,
"createdAt": "2024-06-03T08:15:00Z",
"likedBy": []
},
{
"id": 3,
"message": "Pasta night with friends 🍝❤️",
"category": "food",
"hearts": 8,
"createdAt": "2024-06-05T19:00:00Z",
"likedBy": ["user123", "user456"]
},
{
"id": 4,
"message": "Started a new React project today!",
"category": "project",
"hearts": 4,
"createdAt": "2024-06-06T14:00:00Z",
"likedBy": []
},
{
"id": 5,
"message": "Cleaned the whole apartment and lit some candles 🕯️",
"category": "home",
"hearts": 2,
"createdAt": "2024-06-07T09:00:00Z",
"likedBy": ["user789"]
}
]
22 changes: 22 additions & 0 deletions middlewares/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import jwt from "jsonwebtoken";

const JWT_SECRET = process.env.JWT_SECRET;

export const authenticate = (req, res, next) => {
const authHeader = req.headers.authorization;

if (!authHeader)
return res.status(401).json({ message: "Authorization header missing" });

const token = authHeader.split(" ")[1];

if (!token) return res.status(401).json({ message: "Token missing" });

try {
const decoded = jwt.verify(token, JWT_SECRET);
req.user = decoded;
next();
} catch (error) {
res.status(401).json({ message: "Invalid or expired token" });
}
};
27 changes: 27 additions & 0 deletions models/User.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import bcrypt from "bcrypt";
import mongoose from "mongoose";

const userSchema = new mongoose.Schema({
username: { type: String, required: true, unique: true, minlength: 3 },
email: { type: String, required: true, unique: true, lowercase: true },
password: { type: String, required: true, minlength: 6 },
});

userSchema.pre("save", async function (next) {
if (!this.isModified("password")) return next();

try {
const salt = await bcrypt.genSalt(10);
this.password = await bcrypt.hash(this.password, salt);
next();
} catch (error) {
next(error);
}
});

userSchema.methods.comparePassword = async function (candidatePassword) {
return bcrypt.compare(candidatePassword, this.password);
};

const User = mongoose.model("User", userSchema);
export default User;
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@
"@babel/core": "^7.17.9",
"@babel/node": "^7.16.8",
"@babel/preset-env": "^7.16.11",
"bcrypt": "^6.0.0",
"cors": "^2.8.5",
"dotenv": "^16.5.0",
"express": "^4.17.3",
"nodemon": "^3.0.1"
"express-list-endpoints": "^7.1.1",
"jsonwebtoken": "^9.0.2",
"mongoose": "^8.15.1",
"nodemon": "^3.1.10"
}
}
73 changes: 73 additions & 0 deletions routes/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import express from "express";
import jwt from "jsonwebtoken";

import User from "../models/User.js";

const router = express.Router();
const JWT_SECRET = process.env.JWT_SECRET;

// signing up as a user
router.post("/signup", async (req, res) => {
const { username, email, password } = req.body;

try {
const existingUser = await User.findOne({ $or: [{ email }, { username }] });
if (existingUser) {
return res
.status(400)
.json({ success: false, message: "Username or email already exists." });
}

const newUser = new User({ username, email, password });
await newUser.save();

const token = jwt.sign(
{ id: newUser._id, username: newUser.username },
JWT_SECRET,
{
expiresIn: "7d",
}
);

res.status(201).json({ success: true, message: "User created", token });
} catch (error) {
res
.status(500)
.json({ success: false, message: "Error creating user", error });
}
Comment on lines +32 to +37

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could suggest adding more specific error messages/handling. It was hard to tell why I couldn't register at first. I needed 6 password characters and I was only doing 5. And the email field didnt show any user errors when registering, (it did in the login form). Its possible to use mongoose named errors to get more info; something in this direction:

    if (error.name === "ValidationError") {
      return res.status(400).json({
        success: false,
        errors: error.errors,
        message: "Validation failed",
      })
    }
    res.status(500).json({
      success: false,
      error: error.message,
      message: "Server error - try again later."
    })
  }

});

// login
router.post("/login", async (req, res) => {
const { email, password } = req.body;

try {
const user = await User.findOne({ email });
if (!user) {
return res
.status(401)
.json({ success: false, message: "Invalid email or password" });
}

const isMatch = await user.comparePassword(password);
if (!isMatch) {
return res
.status(401)
.json({ success: false, message: "Invalid email or password" });
}

const token = jwt.sign(
{ id: user._id, username: user.username },
JWT_SECRET,
{
expiresIn: "7d",
}
);

res.status(200).json({ success: true, message: "Logged in", token });
} catch (error) {
res.status(500).json({ success: false, message: "Login error", error });
}
});

export default router;
Loading