-
Notifications
You must be signed in to change notification settings - Fork 30
PR for review & submission of the happy thoughts API (will also open a PR for the frontend) #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
2cd433d
dccb546
f980af9
6e9c2e5
9a388b8
01dcdd6
2fdd7aa
f7d2b05
aed5d75
37ba143
bec0584
bbfeac8
9fbbbfb
67e425f
5eb3668
34eb57d
07d8500
4e88d61
20f9995
6e7c257
2d37369
14a94ae
7d16c70
2c5f5df
37323da
c887bec
a776933
888ca9c
dcbc1a7
b85f82f
dc226b1
745449e
1455749
230ba89
ffc5332
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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"] | ||
}, | ||
{ | ||
"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"] | ||
} | ||
] |
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" }); | ||
} | ||
}; |
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; |
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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:
|
||
}); | ||
|
||
// 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; |
There was a problem hiding this comment.
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 🙌