Skip to content

Commit

Permalink
feat: update blog
Browse files Browse the repository at this point in the history
  • Loading branch information
LivingHopeDev committed Aug 8, 2024
1 parent d5f3b7f commit d6f6e32
Show file tree
Hide file tree
Showing 10 changed files with 433 additions and 100 deletions.
177 changes: 166 additions & 11 deletions src/controllers/BlogController.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { NextFunction, Request, Response } from "express";
import { BlogService } from "../services";
import { ResourceNotFound, ServerError, Forbidden } from "../middleware";

export class BlogController {
private blogService: BlogService;
Expand Down Expand Up @@ -413,14 +414,171 @@ export class BlogController {
});
}
}
/**
* @swagger
* /blog/edit/{id}:
* patch:
* summary: Edit a blog post
* description: Update the details of a blog post including title, content, image URL, tags, categories, and publish date. Only the author can update their blog post.
* tags: [Blog]
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: string
* description: The ID of the blog post to edit
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* title:
* type: string
* description: The title of the blog post
* content:
* type: string
* description: The content of the blog post
* image_url:
* type: string
* description: The URL of the blog post's image
* tags:
* type: string
* description: A comma-separated list of tags for the blog post
* categories:
* type: string
* description: A comma-separated list of categories for the blog post
* publish_date:
* type: string
* format: date-time
* description: The publish date of the blog post
* example:
* title: "Updated Blog Title"
* content: "This is the updated content of the blog post."
* image_url: "http://example.com/image.jpg"
* tags: "technology, AI"
* categories: "Tech News, Artificial Intelligence"
* publish_date: "2023-09-12T10:00:00Z"
* responses:
* 200:
* description: Blog post updated successfully.
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: success
* status_code:
* type: integer
* example: 200
* message:
* type: string
* example: Blog post updated successfully.
* post:
* type: object
* properties:
* blog_id:
* type: string
* example: "12345"
* title:
* type: string
* example: "Updated Blog Title"
* content:
* type: string
* example: "This is the updated content of the blog post."
* tags:
* type: array
* items:
* type: string
* categories:
* type: array
* items:
* type: string
* image_urls:
* type: string
* example: "http://example.com/image.jpg"
* author:
* type: string
* example: "Author Name"
* updated_at:
* type: string
* format: date-time
* example: "2023-09-12T10:00:00Z"
* 400:
* description: Bad Request - Invalid input data.
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: unsuccessful
* status_code:
* type: integer
* example: 400
* message:
* type: string
* example: Invalid request data.
* 403:
* description: Unauthorized - User is not allowed to update this blog post.
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: unsuccessful
* status_code:
* type: integer
* example: 403
* message:
* type: string
* example: Unauthorized access.
* 404:
* description: Blog post not found.
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: unsuccessful
* status_code:
* type: integer
* example: 404
* message:
* type: string
* example: Blog post not found.
* 500:
* description: An unexpected error occurred while processing the request.
* content:
* application/json:
* schema:
* type: object
* properties:
* status:
* type: string
* example: unsuccessful
* status_code:
* type: integer
* example: 500
* message:
* type: string
* example: An unexpected error occurred.
*/

async updateBlog(req: Request, res: Response, next: NextFunction) {
try {
const userId = req.user.id;
const blogId = req.params.id;
const { title, content, image_url, tags, categories } = req.body;
if (!title || !content || image_url || tags || categories) {
}

const updatedBlog = await this.blogService.updateBlog(
blogId,
req.body,
Expand All @@ -430,16 +588,13 @@ export class BlogController {
status: "success",
status_code: 200,
message: "Blog post updated successfully.",
post: updatedBlog,
data: updatedBlog,
});
} catch (error) {
// res.status(500).json({
// status: "unsuccessful",
// status_code: 500,
// message: error.message,
// });
console.log("err", error);
next(error);
if (error instanceof ResourceNotFound || error instanceof Forbidden) {
next(error);
}
next(new ServerError("Internal server error."));
}
}
}
6 changes: 5 additions & 1 deletion src/controllers/FaqController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { FAQService } from "../services";
import { UserRole } from "../enums/userRoles";
import isSuperAdmin from "../utils/isSuperAdmin";
import { Category } from "../models";
import { ServerError, BadRequest } from "../middleware";

const faqService = new FAQService();

Expand Down Expand Up @@ -338,7 +339,10 @@ class FAQController {
status_code: 200,
});
} catch (error) {
next(error);
if (error instanceof BadRequest) {
next(error);
}
next(new ServerError("Internal server error."));
}
}

Expand Down
30 changes: 0 additions & 30 deletions src/controllers/updateBlogController.ts

This file was deleted.

2 changes: 1 addition & 1 deletion src/models/category.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Blog } from "./blog";

@Entity()
export class Category {
@PrimaryGeneratedColumn()
@PrimaryGeneratedColumn("uuid")
id: number;

@Column()
Expand Down
2 changes: 1 addition & 1 deletion src/models/tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Blog } from "./blog";

@Entity()
export class Tag {
@PrimaryGeneratedColumn()
@PrimaryGeneratedColumn("uuid")
id: number;

@Column()
Expand Down
9 changes: 3 additions & 6 deletions src/routes/blog.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { Router } from "express";
import { BlogCommentController } from "../controllers/blogCommentController";
import { BlogController } from "../controllers/BlogController";
// import { createBlogController } from "../controllers/createBlogController"
import { updateBlogController } from "../controllers/updateBlogController";
import { authMiddleware } from "../middleware";
import { authMiddleware, checkPermissions } from "../middleware";
import { requestBodyValidator } from "../middleware/request-validation";
import { createBlogSchema } from "../utils/request-body-validator";
import { UserRole } from "../enums/userRoles";

const blogRouter = Router();
const blogController = new BlogController();
Expand All @@ -26,25 +25,23 @@ blogRouter.get(
);
blogRouter.patch(
"/blog/edit/:id",
requestBodyValidator(createBlogSchema),
authMiddleware,
blogController.updateBlog.bind(blogController),
);
blogRouter.put("/:id", authMiddleware, updateBlogController);

blogRouter.delete(
"/blog/:id",
authMiddleware,
blogController.deleteBlogPost.bind(blogController),
);

//endpoint to create a comment on a blog post
blogRouter.post(
"/blog/:postId/comment",
authMiddleware,
blogCommentController.createComment.bind(blogCommentController),
);

//endpoint to edit a comment on a blog post
blogRouter.patch(
"/blog/:commentId/edit-comment",
authMiddleware,
Expand Down
53 changes: 48 additions & 5 deletions src/services/blog.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Repository } from "typeorm";
import AppDataSource from "../data-source";
import { Category, Tag, User } from "../models";
import { Blog } from "../models/blog";
import { ResourceNotFound } from "../middleware";
import { ResourceNotFound, Forbidden } from "../middleware";

export class BlogService {
getAllComments(mockBlogId: string) {
Expand Down Expand Up @@ -118,27 +118,70 @@ export class BlogService {
throw error;
}
}
async updateBlog(blogId: string, payload: Blog, userId: string) {
async updateBlog(blogId: string, payload: any, userId: string) {
const blog = await this.blogRepository.findOne({
where: { id: blogId },
relations: ["author"],
relations: ["author", "tags", "categories"],
});

if (!blog) {
throw new ResourceNotFound("Blog post not found");
}
if (blog.author.id !== userId) {
throw new Forbidden("You are not authorized to edit this blog post");
}
const user = await this.userRepository.findOne({ where: { id: userId } });
Object.assign(blog, payload, { author: user });

blog.title = payload.title;
blog.content = payload.content;
blog.image_url = payload.image_url;
blog.author = user;
blog.published_at = payload.publish_date;
if (payload.tags) {
const tagsContent = payload.tags.split(",");
const tagEntities = await Promise.all(
tagsContent.map(async (tagName: string) => {
let tag = await this.tagRepository.findOne({
where: { name: tagName },
});
if (!tag) {
tag = this.tagRepository.create({ name: tagName });
await this.tagRepository.save(tag);
}
return tag;
}),
);
blog.tags = tagEntities;
}

if (payload.categories) {
const categoriesContent = payload.categories.split(",");
const categoryEntities = await Promise.all(
categoriesContent.map(async (categoryName: string) => {
let category = await this.categoryRepository.findOne({
where: { name: categoryName },
});
if (!category) {
category = this.categoryRepository.create({ name: categoryName });
await this.categoryRepository.save(category);
}
return category;
}),
);
blog.categories = categoryEntities;
}

const updatedBlog = await this.blogRepository.save(blog);

return {
blog_id: updatedBlog.id,
title: updatedBlog.title,
content: updatedBlog.content,
tags: updatedBlog.tags,
categories: updatedBlog.categories,
image_urls: updatedBlog.image_url,
author: updatedBlog.author.name,
updatedBlog_at: updatedBlog.created_at,
updated_at: updatedBlog.updated_at,
};
}
}
Loading

0 comments on commit d6f6e32

Please sign in to comment.