Skip to content

Commit

Permalink
Merge pull request #62 from DOOMSDAY101/feat/19-implement-backend-for…
Browse files Browse the repository at this point in the history
…-notification-settings

Feat/19 Implement Backend for Notification Settings
  • Loading branch information
Idimmusix authored Jul 21, 2024
2 parents 190b8a4 + 7ce1843 commit 01bd8d7
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 2,187 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ build/
tmp/
temp/
.env
env
env
src/entity
src/ormconfig.ts
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"dayjs": "^1.11.12",
"dotenv": "^16.4.5",
"express": "^4.19.2",
"express-jwt": "^8.4.1",
"handlebars": "^4.7.8",
"jest": "^29.7.0",
"jsonwebtoken": "^9.0.2",
Expand Down
3 changes: 3 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import config from "./config";
import dotenv from "dotenv";
import cors from "cors";
import { userRouter, authRoute } from "./routes";
import { notificationRouter } from "./routes/notificationsettings"
import { routeNotFound, errorHandler } from "./middleware";

dotenv.config();
Expand Down Expand Up @@ -36,6 +37,7 @@ server.use("/api/v1", userRouter);
server.use("/api/v1/auth", authRoute);
server.use(routeNotFound);
server.use(errorHandler);
server.use("/api/v1/settings", notificationRouter);

AppDataSource.initialize()
.then(async () => {
Expand All @@ -46,3 +48,4 @@ AppDataSource.initialize()
.catch((error) => console.error(error));

export default server;

23 changes: 23 additions & 0 deletions src/middleware/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Request, Response, NextFunction } from "express";
import jwt from "jsonwebtoken";

interface CustomRequest extends Request {
user?: any;
}
export const authenticateJWT = (req: Request, res: Response, next: NextFunction) => {
const authHeader = req.headers['authorization'];

if (authHeader) {
const token = authHeader.split(' ')[1];

jwt.verify(token, process.env.AUTH_SECRET, (err, user) => {
if (err) {
return res.status(400).json({ message: "JWT token is invalid.", status: 400 });
}
(req as CustomRequest).user = user; next();
});
}
else {
return res.status(401).json({ message: "JWT token is missing or invalid.", status: 401 });
}
}
78 changes: 78 additions & 0 deletions src/routes/notificationsettings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { authenticateJWT } from '../middleware/auth'
import { Router } from "express";
import { NotificationSetting } from '../models/notification'
import { Request, Response } from "express";

// TO validate all required fields in post /api/notification-settings
interface NotificationSettings {
user_id: number;
email_notifications: boolean;
push_notifications: boolean;
sms_notifications: boolean;
}

const requiredFields: (keyof NotificationSettings)[] = [
'user_id',
'email_notifications',
'push_notifications',
'sms_notifications'
];
const notificationRouter = Router();
const validateFields = (body: Partial<NotificationSettings>) => {
const missingFields = requiredFields.filter(field => body[field] === undefined);

if (missingFields.length > 0) {
return {
valid: false,
message: `Missing required fields: ${missingFields.join(', ')}`
};
}

return { valid: true };
};

// Create notification setting for a user
const CreateNotification = async (req: Request, res: Response) => {
try {
const validation = validateFields(req.body);

if (!validation.valid) {
return res.status(400).json({ status: "error", code: 400, message: validation.message });
}
const { user_id } = req.body;

// Check if a notification setting already exists for this user_id
const existingSetting = await NotificationSetting.findOne({ where: { user_id } });

const newSetting = NotificationSetting.create(req.body);
const result = await NotificationSetting.save(newSetting);
res.status(200).json({ status: "success", code: 200, data: result });

if (existingSetting) {
return res.status(409).json({ status: "error", code: 409, message: "Notification settings for this user already exist." });
}

} catch (error) {
console.log(error)
res.status(500).json({ status: "error", code: 500, message: "Error creating user notification" });
}
}

// Get notification setting
const GetNotification = async (req: Request, res: Response) => {
try {
const settings = await NotificationSetting.findOne({ where: { user_id: String(req.params.user_id) } });
if (settings === null) {
return res.status(404).json({ status: "Not found", message: "The user with the requested id cannot be found" })
}
res.status(200).json({ status: "success", code: 200, data: settings });

} catch (error) {
res.status(500).json({ status: "error", code: 500, message: error.message });
}
}

notificationRouter.post('/notification-settings', authenticateJWT, CreateNotification);
notificationRouter.get("/notification-settings/:user_id", authenticateJWT, GetNotification);

export { notificationRouter };
2 changes: 2 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"sourceMap": true,
"skipLibCheck": true,
"include": ["src/**/*"],
"typeRoots": ["src/types"]
}
}
Loading

0 comments on commit 01bd8d7

Please sign in to comment.