From 6ab79a7812e1329adcf6434857486de1aeedf7ee Mon Sep 17 00:00:00 2001 From: Wendy Gardiel <34959525+whend12@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:29:37 +0700 Subject: [PATCH] BE notfix --- .gitignore | 2 ++ controllers/blogController.js | 52 ++++++++++++++++++++++++++++++----- index.js | 5 ++++ models/blogModel.js | 5 ++++ package-lock.json | 23 ++++++++++++++++ package.json | 1 + routes/blogRoutes.js | 8 ++++-- user.rest | 9 +++--- 8 files changed, 90 insertions(+), 15 deletions(-) diff --git a/.gitignore b/.gitignore index 5871fca..be139a9 100644 --- a/.gitignore +++ b/.gitignore @@ -115,3 +115,5 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +uploads/ \ No newline at end of file diff --git a/controllers/blogController.js b/controllers/blogController.js index b2e94e0..6f00a17 100644 --- a/controllers/blogController.js +++ b/controllers/blogController.js @@ -26,20 +26,35 @@ export const getBlogById = async (req, res) => { } }; +// Get blog by slug +export const getBlogBySlug = async (req, res) => { + try { + const blog = await blogModel.findOne({ + where: { slug: req.params.slug }, + include: [{ model: blogImage, as: "images" }], + }); + + if (!blog) return res.status(404).json({ message: "Blog not found" }); + + res.json(blog); + } catch (error) { + res.status(500).json({ message: error.message }); + } +}; + // Create a new blog export const createBlog = async (req, res) => { try { const { title, description } = req.body; - // Pastikan ada file yang diunggah if (!req.files || req.files.length === 0) { return res.status(400).json({ message: "Minimal 1 gambar diperlukan!" }); } - // Simpan data blog - const blog = await blogModel.create({ title, description }); + const slug = generateSlug(title); // 🔥 generate slug di sini + + const blog = await blogModel.create({ title, description, slug }); - // Simpan gambar ke database const imagePaths = req.files.map((file) => ({ blogId: blog.id, imageUrl: `/uploads/${file.filename}`, @@ -47,9 +62,8 @@ export const createBlog = async (req, res) => { await blogImage.bulkCreate(imagePaths); - // Ambil data blog beserta gambar setelah disimpan const newBlog = await blogModel.findByPk(blog.id, { - include: [{ model: blogImage, as: "images" }], // Pastikan alias sesuai + include: [{ model: blogImage, as: "images" }], }); res.status(201).json({ @@ -61,12 +75,36 @@ export const createBlog = async (req, res) => { } }; +const generateSlug = (title) => { + return title + .toLowerCase() + .replace(/\s+/g, "-") + .replace(/[^\w-]+/g, ""); +}; + // Update a blog export const updateBlog = async (req, res) => { try { const blog = await blogModel.findByPk(req.params.id); if (!blog) return res.status(404).json({ message: "Blog not found" }); - await blog.update(req.body); + + const { title, description, slug } = req.body; + + // Tentukan slug baru (jika ada title baru dan tidak ada slug manual) + let updatedSlug = blog.slug; // default: slug lama + if (title && !slug) { + updatedSlug = generateSlug(title); + } else if (slug) { + updatedSlug = slug; + } + + // Update data + await blog.update({ + title: title ?? blog.title, + description: description ?? blog.description, + slug: updatedSlug, + }); + res.json(blog); } catch (error) { res.status(500).json({ message: error.message }); diff --git a/index.js b/index.js index f7cab93..f2eb7f4 100644 --- a/index.js +++ b/index.js @@ -3,11 +3,14 @@ import db from "./config/database.js"; import dotenv from "dotenv"; import router from "./routes/index.js"; // Hanya import 1 router import cors from "cors"; +import cookieParser from "cookie-parser"; +import path from "path"; const app = express(); dotenv.config(); const connectToDatabase = async () => { + // await db.sync({ force: true }); try { await db.authenticate(); console.log("Database connected..."); @@ -18,8 +21,10 @@ const connectToDatabase = async () => { connectToDatabase(); +app.use(cookieParser()); app.use(cors()); app.use(express.json()); app.use(router); +app.use("/uploads", express.static(path.join(process.cwd(), "uploads"))); app.listen(5000, () => console.log("server running at port 5000")); diff --git a/models/blogModel.js b/models/blogModel.js index d389d9a..36c1b82 100644 --- a/models/blogModel.js +++ b/models/blogModel.js @@ -13,6 +13,11 @@ const Blog = db.define("blog", { type: DataTypes.TEXT, allowNull: false, }, + slug: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, }); // Definisi relasi dengan alias 'images' diff --git a/package-lock.json b/package-lock.json index 95b0965..a1f0b12 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "license": "ISC", "dependencies": { "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.7", "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", @@ -455,6 +456,28 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", + "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", + "license": "MIT", + "dependencies": { + "cookie": "0.7.2", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/package.json b/package.json index 0019ad3..b805649 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "bcrypt": "^5.1.1", + "cookie-parser": "^1.4.7", "cors": "^2.8.5", "dotenv": "^16.4.7", "express": "^4.21.2", diff --git a/routes/blogRoutes.js b/routes/blogRoutes.js index 331ee7e..8aa2fdc 100644 --- a/routes/blogRoutes.js +++ b/routes/blogRoutes.js @@ -2,6 +2,7 @@ import express from "express"; import { getAllBlogs, getBlogById, + getBlogBySlug, createBlog, updateBlog, deleteBlog, @@ -13,8 +14,9 @@ const router = express.Router(); router.get("/blog", getAllBlogs); router.get("/blog/:id", getBlogById); -router.post("/blog", verifyToken, upload.array("images", 5), createBlog); -router.patch("/blog/:id", verifyToken, updateBlog); -router.delete("/blog/:id", verifyToken, deleteBlog); +router.get("/blog/slug/:slug", getBlogBySlug); +router.post("/blog", upload.array("images", 5), createBlog); +router.put("/blog/:id", updateBlog); +router.delete("/blog/:id", deleteBlog); export default router; diff --git a/user.rest b/user.rest index 2e9d6d6..f174244 100644 --- a/user.rest +++ b/user.rest @@ -1,9 +1,9 @@ -POST http://localhost:5000/user/register +POST http://localhost:5000/users/register Content-type: application/json { - "name" : "admin2", - "email" : "admin2@admin.com", + "name" : "admin", + "email" : "admin@admin.com", "password" : "admin123", "confirmPassword" : "admin123" } @@ -20,6 +20,5 @@ Content-Type: application/json ### -GET http://localhost:5000/users -Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOjEsIm5hbWUiOiJhZG1pbiIsImVtYWlsIjoiYWRtaW5AYWRtaW4uY29tIiwiaWF0IjoxNzQzMDQ0NDg5LCJleHAiOjE3NDMwNDQ1MDl9.m_tpB5DPpFDIaSWQki8jCKWqCbSzsBaKqh3W35a32XI +GET http://localhost:5000/users/token