Skip to content

Commit 7c735a0

Browse files
committed
added login feature
1 parent 25a8cca commit 7c735a0

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

shatter-backend/src/controllers/auth_controller.ts

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Request, Response } from 'express';
22
import { User } from '../models/user_model';
3-
import { hashPassword } from '../utils/password_hash';
3+
import { hashPassword, comparePassword } from '../utils/password_hash';
44

55
// Email validation regex
66
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
@@ -90,3 +90,78 @@ export const signup = async (req: Request, res: Response) => {
9090
};
9191

9292

93+
/**
94+
* POST /api/auth/login
95+
* Authenticate user and log them in
96+
*
97+
* @param req.body.email - User's email
98+
* @param req.body.password - User's plain text password
99+
* @returns 200 with userId on success
100+
*/
101+
export const login = async (req: Request, res: Response) => {
102+
try {
103+
// 1 - extract data from req body
104+
const { email, password } = req.body as {
105+
email?: string;
106+
password?: string;
107+
};
108+
109+
// 2 - validate required fields
110+
if (!email || !password) {
111+
return res.status(400).json({
112+
error: 'Email and password are required'
113+
});
114+
}
115+
116+
// 3 - normalize email
117+
const normalizedEmail = email.toLowerCase().trim();
118+
119+
// 4 - validate email format
120+
if (!EMAIL_REGEX.test(normalizedEmail)) {
121+
return res.status(400).json({
122+
error: 'Invalid email format'
123+
});
124+
}
125+
126+
// 5 - find user by email
127+
const user = await User.findOne({ email: normalizedEmail })
128+
.select('+passwordHash'); // need this since queries don't return passwordHash by default
129+
130+
// 6 - check if user exists
131+
if (!user) {
132+
// for security purposes I won't include whether email exists or not
133+
return res.status(401).json({
134+
error: 'Invalid credentials'
135+
});
136+
}
137+
138+
// 7 - verify password
139+
const isPasswordValid = await comparePassword(password, user.passwordHash);
140+
141+
if (!isPasswordValid) {
142+
return res.status(401).json({
143+
error: 'Invalid credentials'
144+
});
145+
}
146+
147+
// 8 - update lastLogin stamp
148+
user.lastLogin = new Date();
149+
await user.save(); // save the updated user
150+
151+
// 9 - return success
152+
res.status(200).json({
153+
message: 'Login successful',
154+
userId: user._id
155+
// TODO: figure out a way to add JWT token here
156+
});
157+
158+
} catch (err: any) {
159+
console.error('POST /api/auth/login error:', err);
160+
161+
// Generic error Response
162+
res.status(500).json({
163+
error: 'Login failed'
164+
});
165+
}
166+
};
167+
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { Router } from 'express';
2-
import { signup } from '../controllers/auth_controller';
2+
import { signup, login } from '../controllers/auth_controller';
33

44
const router = Router();
55

6-
// create new user account
6+
// POST /api/auth/signup - create new user account
77
router.post('/signup', signup);
88

9+
// POST /api/auth/login - authenticate user
10+
router.post('/login', login);
11+
912
export default router;

0 commit comments

Comments
 (0)