Skip to content

Commit 25a8cca

Browse files
committed
created signup option and added validation
1 parent 82db52e commit 25a8cca

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

shatter-backend/src/app.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Express framework gives us fucnctions to creeate web server, handle routes, process HTTP req and send responses
22
import express from 'express';
33
import userRoutes from './routes/user_route.ts'; // these routes define how to handel requests to /api/users
4+
import authRoutes from './routes/auth_routes';
45

56
// Creating express application as a single "app" object, started in server.ts
67
// This object represents entire web server and will be used to:
@@ -20,6 +21,7 @@ app.get('/', (_req, res) => {
2021
// Mounts the user routes under the path 'api/users'
2122
// any routes defined in user_route.ts will be accessible with URLs starting with /api/users
2223
app.use('/api/users', userRoutes);
24+
app.use('/api/auth', authRoutes);
2325

2426

2527
// Export the configured Express app, so that server.ts can import it
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import { Request, Response } from 'express';
2+
import { User } from '../models/user_model';
3+
import { hashPassword } from '../utils/password_hash';
4+
5+
// Email validation regex
6+
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
7+
8+
/**
9+
* POST /api/auth/signup
10+
* Create new user account
11+
*
12+
* @param req.body.name - User's display name
13+
* @param req.body.email - User's email
14+
* @param req.body.password - User's plain text password
15+
* @returns 201 with userId on success
16+
*/
17+
export const signup = async (req: Request, res: Response) => {
18+
try {
19+
// extract data from req body
20+
const { name, email, password } = req.body as {
21+
name?: string;
22+
email?: string;
23+
password?: string;
24+
};
25+
26+
// validate required fields
27+
if (!name || !email || !password) {
28+
return res.status(400).json({
29+
error: 'name, email and password are required'
30+
});
31+
}
32+
33+
// normalize email before validation
34+
const normalizedEmail = email.toLowerCase().trim();
35+
36+
// validate email format
37+
if (!EMAIL_REGEX.test(normalizedEmail)) {
38+
return res.status(400).json({
39+
error: 'Invalid email format'
40+
});
41+
}
42+
43+
// validate password length
44+
if (password.length < 8) {
45+
return res.status(400).json({
46+
error: 'Password must be at least 8 characters long'
47+
});
48+
}
49+
50+
// check if email already exists
51+
const existingUser = await User.findOne({ email: normalizedEmail }).lean();
52+
if (existingUser) {
53+
return res.status(409).json({
54+
error: 'Email already exists'
55+
});
56+
}
57+
58+
// hash the password
59+
const passwordHash = await hashPassword(password);
60+
61+
// create user in database
62+
// mongoose automatically adds createdAt, updatedAt, _id with User.create
63+
const newUser = await User.create({
64+
name,
65+
email: normalizedEmail,
66+
passwordHash
67+
});
68+
69+
// return success
70+
res.status(201).json({
71+
message: 'User created successfully',
72+
userId: newUser._id
73+
});
74+
75+
} catch (err: any) {
76+
console.error('POST /api/auth/signup error:', err);
77+
78+
// handle duplicate email error form MongoDB
79+
if (err?.code === 11000) {
80+
return res.status(409).json({
81+
error: 'Email already exists'
82+
});
83+
}
84+
85+
// Generic error Response
86+
res.status(500).json({
87+
error: 'Failed to create user'
88+
});
89+
}
90+
};
91+
92+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Router } from 'express';
2+
import { signup } from '../controllers/auth_controller';
3+
4+
const router = Router();
5+
6+
// create new user account
7+
router.post('/signup', signup);
8+
9+
export default router;

0 commit comments

Comments
 (0)