Skip to content

Commit f49005a

Browse files
committed
adding user registration end points
1 parent aa9894a commit f49005a

File tree

5 files changed

+122
-0
lines changed

5 files changed

+122
-0
lines changed
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { Request, Response } from 'express';
2+
import { StatusCodes } from 'http-status-codes';
3+
import { registerService } from '@/services/registration/register-logic';
4+
import type { IRegisterPayload } from '@/services/registration/register-inputs';
5+
6+
export async function register(req: Request, res: Response) {
7+
//Extract the registration data from the request body
8+
const { email, username, password, firstName, lastName }: Partial<IRegisterPayload> = req.body;
9+
10+
//Validate input
11+
if (!username || !password || !email || !firstName || !lastName) {
12+
return res.status(StatusCodes.UNPROCESSABLE_ENTITY).json('Malformed Request');
13+
}
14+
15+
//Call the registration service
16+
const { code, data, error } = await registerService({
17+
email,
18+
username,
19+
firstName,
20+
lastName,
21+
password,
22+
});
23+
24+
//Handle errors
25+
if (error || code !== StatusCodes.CREATED || !data) {
26+
const sanitizedErr = error?.message ?? 'An error occurred during registration.';
27+
return res.status(code).json(sanitizedErr);
28+
}
29+
30+
//Set JWT token as an HTTP-only cookie
31+
return res
32+
.status(StatusCodes.CREATED)
33+
.cookie('jwtToken', data.cookie, { httpOnly: true }) // Set the JWT token as a cookie
34+
.json({
35+
message: 'User registered successfully',
36+
user: data.user, // Return user data if needed
37+
});
38+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import express from 'express';
2+
import { register } from '@/controllers/registration/registerController';
3+
4+
const router = express.Router();
5+
// Route to handle user registration
6+
router.post('/', register);
7+
8+
export default router;

backend/user/src/server.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import express, { json } from 'express';
22
import pino from 'pino-http';
33
import { db } from './lib/db';
44
import authRoutes from './routes/auth';
5+
import registerRoutes from './routes/register';
56
import helmet from 'helmet';
67
import { sql } from 'drizzle-orm';
78
import { logger } from './lib/utils';
@@ -12,6 +13,7 @@ app.use(pino());
1213
app.use(json());
1314
app.use(helmet());
1415
app.use('/auth', authRoutes);
16+
app.use('/register', registerRoutes);
1517
app.get('/', async (_req, res) => {
1618
res.json({
1719
message: 'OK',
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export type IRegisterPayload = {
2+
email: string;
3+
username: string;
4+
firstName: string;
5+
lastName: string;
6+
password: string;
7+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { or, eq, getTableColumns } from 'drizzle-orm';
2+
import { StatusCodes } from 'http-status-codes';
3+
import bcrypt from 'bcrypt';
4+
import jwt from 'jsonwebtoken';
5+
import { db, users } from '@/lib/db';
6+
import type { IRegisterPayload } from './register-inputs';
7+
8+
const _JWT_SECRET_KEY = 'secret';
9+
10+
const _getSchema = () => {
11+
const { id, email, username, firstName, lastName, password } = getTableColumns(users);
12+
return {
13+
id,
14+
email,
15+
username,
16+
firstName,
17+
lastName,
18+
password,
19+
};
20+
};
21+
22+
export const registerService = async (payload: IRegisterPayload) => {
23+
const { email, username, firstName, lastName, password } = payload;
24+
25+
//check if user already exists (by username or email)
26+
const existingUsers = await db
27+
.select(_getSchema())
28+
.from(users)
29+
.where(or(eq(users.username, username), eq(users.email, email)))
30+
.limit(1);
31+
32+
if (existingUsers.length > 0) {
33+
return {
34+
code: StatusCodes.CONFLICT,
35+
error: {
36+
message: 'User with this username or email already exists',
37+
},
38+
};
39+
}
40+
41+
//hash the password
42+
const hashedPassword = bcrypt.hashSync(password, 10); // Use bcrypt to hash the password
43+
44+
//insert new user into the database
45+
const [newUser] = await db
46+
.insert(users)
47+
.values({
48+
email,
49+
username,
50+
firstName,
51+
lastName,
52+
password: hashedPassword, //store the hashed password
53+
})
54+
.returning(_getSchema());
55+
56+
// generate JWT token for the new user
57+
const jwtToken = jwt.sign({ id: newUser.id }, _JWT_SECRET_KEY);
58+
59+
// return success response with the JWT token
60+
return {
61+
code: StatusCodes.CREATED,
62+
data: {
63+
cookie: jwtToken,
64+
user: newUser,
65+
},
66+
};
67+
};

0 commit comments

Comments
 (0)