Skip to content

Commit

Permalink
Merge pull request #73 from CollinDex/feat/9-Help_Center_Update_Topic
Browse files Browse the repository at this point in the history
[FEAT] HELP CENTER - UPDATE TOPIC #9
  • Loading branch information
Idimmusix authored Jul 22, 2024
2 parents 199db35 + ad6c68c commit ee30a9b
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 1 deletion.
64 changes: 64 additions & 0 deletions src/controllers/HelpController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// src/controllers/UserController.ts
import { Request, Response } from "express";
import { HelpService } from "../services";
import { HttpError } from "../middleware";

class HelpController {
private helpService: HelpService;

constructor() {
this.helpService = new HelpService();
}

async createTopic(req: Request, res:Response):Promise<void> {
try {
const topic = await this.helpService.create(req);
res.status(201).json({
success: true,
message: 'Topic Created Successfully',
data: {
article_id: topic.id,
content: topic.content,
author: topic.author,
title: topic.title,
createdAt: topic.createdAt,
updatedAt: topic.updatedAt
},
status_code: 201
});
} catch (error) {
if (error instanceof HttpError) {
res.status(error.status).json({message: error.message});
} else {
res.status(500).json({ message: error.message || "Internal Server Error" });
}
}
}

async updateTopic(req: Request, res:Response):Promise<void> {
try {
const topic = await this.helpService.update(req);
res.status(200).json({
success: true,
message: 'Topic Updated Successfully',
data: {
article_id: topic.id,
content: topic.content,
author: topic.author,
title: topic.title,
createdAt: topic.createdAt,
updatedAt: topic.updatedAt
},
status_code: 200
});
} catch (error) {
if (error instanceof HttpError) {
res.status(error.status).json({message: error.message});
} else {
res.status(500).json({ message: error.message || "Internal Server Error" });
}
}
}
}

export default HelpController;
3 changes: 2 additions & 1 deletion src/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// silence is golden
export * from "./AuthController";
export * from "./UserController";
export * from "./NotificationController"
export * from "./HelpController";
export * from "./NotificationController";
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import cors from "cors";
import {
userRouter,
authRoute,
helpRouter,
testimonialRoute,
notificationRouter,
smsRouter,
Expand Down Expand Up @@ -43,6 +44,7 @@ server.get("/", (req: Request, res: Response) => {
});
server.use("/api/v1", userRouter, orgRouter);
server.use("/api/v1/auth", authRoute);
server.use("/api/v1/help-center", helpRouter);
server.use("/api/v1/sms", smsRouter);
server.use("/api/v1", testimonialRoute);
server.use("/api/v1/docs", swaggerUi.serve, swaggerUi.setup(swaggerSpec));
Expand Down
10 changes: 10 additions & 0 deletions src/routes/help-center.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// src/routes/help-center.ts
import { Router } from "express";
import HelpController from "../controllers/HelpController";
import { authMiddleware, verifyAdmin } from "../services";

const helpRouter = Router();
const helpController = new HelpController();
helpRouter.post("/topics", authMiddleware, helpController.createTopic.bind(helpController));
helpRouter.patch("/topics/:id", authMiddleware, helpController.updateTopic.bind(helpController));
export { helpRouter };
1 change: 1 addition & 0 deletions src/routes/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// silently ignore
export * from "./auth";
export * from "./user";
export * from "./help-center";
export * from "./testimonial";
export * from "./sms";
export * from "./notificationsettings";
126 changes: 126 additions & 0 deletions src/services/help.services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// src/services/HelpService.ts
import { NextFunction, Request, Response } from "express";
import jwt from "jsonwebtoken";
import { HelpCenterTopic } from "../models";
import { User } from "../models";
import { AppDataSource } from "../data-source";
import { HttpError } from "../middleware";
import config from "../config";


export class HelpService {

public async create (req:Request): Promise<HelpCenterTopic> {
try {
const { title, content, author} = req.body;

//Validate Input
if (!title || !content || !author) {
throw new HttpError(422, 'Validation failed: Title, content, and author are required');
};

//Check for Existing Title
const articleRepository = AppDataSource.getRepository(HelpCenterTopic);
const existingTitle = await articleRepository.findOne({ where: { title }});
if (existingTitle) {
throw new HttpError(422, 'Article already exists');
};

const articleEntity = articleRepository.create({title, content, author});
const article = await articleRepository.save(articleEntity);
return article;

} catch (error) {
throw new HttpError(error.status || 500, error.message || error);
}
};

public async update (req:Request):Promise<HelpCenterTopic>{
try {
const { title, content, author} = req.body;
const article_id = req.params.id;

//Get article repo
const articleRepository = AppDataSource.getRepository(HelpCenterTopic);

// Check if article exists
const existingArticle = await articleRepository.findOne({ where: { id: article_id } });

if (!existingArticle) {
throw new HttpError(404, 'Not Found');
};

//Update Article on DB
await articleRepository.update(article_id, {title, content, author});

//Fetch Updated article
const newArticle = await articleRepository.findOne({ where: { id: article_id } });
return newArticle;

} catch (error) {
console.error(error);
throw new HttpError(error.status || 500, error.message || error);
};
}

}

export const authMiddleware = (req:Request, res:Response, next:NextFunction) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];

if (!token) {
return res.status(401).json(
{
success: false,
message: 'Access denied. No token provided',
status_code: 401
});
}

try {
const verified = jwt.verify(token, config.TOKEN_SECRET);
if (verified){
next();
}
} catch (error) {
res.status(401).json(
{
success: false,
message: 'Access denied. Invalid token',
status_code: 401
});
}
};

export const verifyAdmin = async (req: Request, res: Response, next: NextFunction) => {
const authHeader = req.headers['authorization'];
const token = authHeader && authHeader.split(' ')[1];
try {
const decodedToken = jwt.decode(token);

if (typeof decodedToken === 'string' || !decodedToken) {
return res.status(401).json({
success: false,
message: 'Access denied. Invalid token',
status_code: 401
});
}

const userRepository = AppDataSource.getRepository(User);
const user = await userRepository.findOne({ where: { id: decodedToken.userId } });
console.log(user.role);

if (user.role !== 'admin' ) {
return res.status(403).json({
success: false,
message: "Access denied! You are not an admin",
status_code: 403
});
}

next();
} catch (error) {
res.status(401).json({ status: 'error', message: 'Access denied. Invalid token' });
}
};
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./auth.services";
export * from "./user.services";
export * from "./help.services";

0 comments on commit ee30a9b

Please sign in to comment.