Skip to content

Commit 30ce626

Browse files
committed
✨ Implement error handling for backend APIs
1 parent d5e4e8b commit 30ce626

3 files changed

Lines changed: 103 additions & 53 deletions

File tree

backend/models/User.js

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,44 @@ const mongoose = require("mongoose");
22
const bcrypt = require("bcryptjs");
33

44
const UserSchema = new mongoose.Schema({
5-
username: {
6-
type: String,
7-
required: true,
8-
unique: true,
9-
},
10-
email: {
11-
type: String,
12-
required: true,
13-
unique: true,
14-
},
15-
password: {
16-
type: String,
17-
required: true,
18-
},
19-
});
20-
21-
UserSchema.pre('save', async function (next) {
5+
username: {
6+
type: String,
7+
required: [true, "Username is required"],
8+
unique: true,
9+
trim: true,
10+
},
11+
email: {
12+
type: String,
13+
required: [true, "Email is required"],
14+
unique: true,
15+
trim: true,
16+
lowercase: true,
17+
match: [/.+\@.+\..+/, "Please enter a valid email address"],
18+
},
19+
password: {
20+
type: String,
21+
required: [true, "Password is required"],
22+
minlength: [6, "Password must be at least 6 characters long"],
23+
},
24+
}, { timestamps: true });
2225

23-
if (!this.isModified('password'))
24-
return next();
26+
// Pre-save password hash
27+
UserSchema.pre("save", async function (next) {
28+
if (!this.isModified("password")) return next();
2529

26-
try {
27-
const salt = await bcrypt.genSalt(10);
28-
this.password = await bcrypt.hash(this.password, salt);
29-
next();
30-
} catch (err) {
31-
return next(err);
32-
}
30+
try {
31+
const salt = await bcrypt.genSalt(10);
32+
this.password = await bcrypt.hash(this.password, salt);
33+
return next();
34+
} catch (err) {
35+
console.error("Password Hashing Error:", err.message);
36+
return next(err);
37+
}
3338
});
3439

3540
// Compare passwords during login
3641
UserSchema.methods.comparePassword = async function (enteredPassword) {
37-
return await bcrypt.compare(enteredPassword, this.password);
42+
return await bcrypt.compare(enteredPassword, this.password);
3843
};
3944

4045
module.exports = mongoose.model("User", UserSchema);

backend/routes/auth.js

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,60 @@ const router = express.Router();
55

66
// Signup route
77
router.post("/signup", async (req, res) => {
8-
9-
const { username, email, password } = req.body;
8+
const { username, email, password } = req.body;
109

1110
try {
12-
const existingUser = await User.findOne( {email} );
11+
const existingUser = await User.findOne({ email });
1312

14-
if (existingUser)
15-
return res.status(400).json( {message: 'User already exists'} );
13+
if (existingUser) {
14+
return res.status(400).json({ message: 'User already exists' });
15+
}
1616

17-
const newUser = new User( {username, email, password} );
17+
const newUser = new User({ username, email, password });
1818
await newUser.save();
19-
res.status(201).json( {message: 'User created successfully'} );
19+
20+
return res.status(201).json({ message: 'User created successfully' });
2021
} catch (err) {
21-
res.status(500).json({ message: 'Error creating user', error: err.message });
22+
console.error("Signup Error:", err.message);
23+
return res.status(500).json({
24+
message: 'Error creating user',
25+
error: err.message
26+
});
2227
}
2328
});
2429

2530
// Login route
26-
router.post("/login", passport.authenticate('local'), (req, res) => {
27-
res.status(200).json( { message: 'Login successful', user: req.user } );
31+
router.post("/login", (req, res, next) => {
32+
passport.authenticate('local', (err, user, info) => {
33+
if (err) {
34+
console.error("Login Error:", err.message);
35+
return res.status(500).json({ message: 'Internal Server Error', error: err.message });
36+
}
37+
38+
if (!user) {
39+
return res.status(401).json({ message: 'Invalid credentials', error: info?.message || 'Authentication failed' });
40+
}
41+
42+
req.logIn(user, (err) => {
43+
if (err) {
44+
console.error("Session Error:", err.message);
45+
return res.status(500).json({ message: 'Login failed', error: err.message });
46+
}
47+
48+
return res.status(200).json({ message: 'Login successful', user });
49+
});
50+
})(req, res, next);
2851
});
2952

3053
// Logout route
3154
router.get("/logout", (req, res) => {
32-
3355
req.logout((err) => {
34-
35-
if (err)
56+
if (err) {
57+
console.error("Logout Error:", err.message);
3658
return res.status(500).json({ message: 'Logout failed', error: err.message });
37-
else
38-
res.status(200).json({ message: 'Logged out successfully' });
59+
}
60+
61+
return res.status(200).json({ message: 'Logged out successfully' });
3962
});
4063
});
4164

backend/server.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,51 @@ require('./config/passportConfig');
1111

1212
const app = express();
1313

14-
// CORS configuration
15-
app.use(cors('*'));
14+
// ✅ CORS configuration (recommended)
15+
app.use(cors({
16+
origin: '*', // You can replace * with specific domains in production
17+
credentials: true,
18+
}));
1619

17-
// Middleware
20+
// Middleware
1821
app.use(bodyParser.json());
22+
1923
app.use(session({
2024
secret: process.env.SESSION_SECRET,
2125
resave: false,
2226
saveUninitialized: false,
2327
}));
28+
2429
app.use(passport.initialize());
2530
app.use(passport.session());
2631

27-
// Routes
32+
// Routes
2833
const authRoutes = require('./routes/auth');
2934
app.use('/api/auth', authRoutes);
3035

31-
// Connect to MongoDB
32-
mongoose.connect(process.env.MONGO_URI, {}).then(() => {
33-
console.log('Connected to MongoDB');
34-
app.listen(process.env.PORT, () => {
35-
console.log(`Server running on port ${process.env.PORT}`);
36+
// ✅ Fallback route for 404 Not Found
37+
app.use((req, res, next) => {
38+
res.status(404).json({ message: 'Route not found' });
39+
});
40+
41+
// ✅ Global error-handling middleware
42+
app.use((err, req, res, next) => {
43+
console.error('Unhandled Error:', err.stack);
44+
res.status(err.status || 500).json({
45+
message: err.message || 'Internal Server Error',
46+
error: process.env.NODE_ENV === 'production' ? undefined : err.stack,
3647
});
37-
}).catch((err) => {
38-
console.log('MongoDB connection error:', err);
3948
});
49+
50+
// ✅ Connect to MongoDB and start server
51+
mongoose.connect(process.env.MONGO_URI, {})
52+
.then(() => {
53+
console.log('Connected to MongoDB');
54+
app.listen(process.env.PORT, () => {
55+
console.log(`Server running on port ${process.env.PORT}`);
56+
});
57+
})
58+
.catch((err) => {
59+
console.error('MongoDB connection error:', err);
60+
process.exit(1); // exit the process on DB failure
61+
});

0 commit comments

Comments
 (0)