Skip to content

Latest commit

 

History

History
283 lines (264 loc) · 11.1 KB

README.md

File metadata and controls

283 lines (264 loc) · 11.1 KB

NODEJS BLOG - Demo

Demo link takes some time to load. Thanks for being petient!



Preview

About The Project

This project is a personal blog website created to document my Software Engineering journey. It features an admin dashboard for managing posts, user authentication, and a responsive design. The blog allows me to share insights, record my learning path, and provide valuable content related to software development and programming.

Features:

  • Home Page: Displays recent blog posts and provides navigation links.
  • Admin Dashboard: Accessible only after login, it allows managing blog posts with options to create, edit, and delete posts.
  • User Authentication: Includes admin login functionality with middleware for checking authentication on protected routes.
  • Post Management: Functionality to create new posts, edit existing posts, and delete posts.
  • Search Functionality: Allows searching posts by title and body content.
  • Responsive Design: Ensures the blog is accessible and usable on various devices with different screen sizes.
  • Styled Components: Utilizes custom fonts, colors, and styled buttons and forms for a consistent and attractive appearance.****

Built With

  • Nodejs
  • Express
  • MongoDB
  • EJS

Project Directory

BLOG
├── node_modules
├── public
│   ├── css
│   │   └── style.css
│   ├── img
│   │   ├── articles.gif
│   │   ├── blog.png
│   │   ├── blog1.gif
│   │   ├── close.png
│   │   ├── Home.gif
│   │   ├── plus.png
│   │   ├── Search.gif
│   │   └── signout.gif
│   └── js
│       └── script.js
├── server
│   ├── config
│   ├── helpers
│   ├── models
│   └── routes
├── views
│   ├── admin
│   │   ├── add-post.ejs
│   │   ├── dashboard.ejs
│   │   ├── edit-post.ejs
│   │   └── index.ejs
│   ├── layouts
│   │   ├── admin.ejs
│   │   └── main.ejs
│   ├── partials
│   │   ├── footer.ejs
│   │   ├── header_admin.ejs
│   │   ├── header.ejs
│   │   └── search.ejs
│   ├── about.ejs
│   ├── index.ejs
│   ├── post.ejs
│   └── search.ejs
├── .env
├── .gitignore
├── app.js
├── package-lock.json
└── package.json 

Usage

Authentication Middleware

  • The authMiddleware function is a crucial part of the application, ensuring that only authenticated users can access certain routes. This middleware checks for a valid JSON Web Token (JWT) in the request cookies and verifies it before allowing access to protected routes.
  • How It Works

  1. Token Retrieval: The middleware first attempts to retrieve the token from the cookies.
  2. Token Validation: If a token is found, it is verified using the jsonwebtoken library and a secret key.
  3. User Identification: If the token is valid, the middleware decodes the token to extract the user ID and attaches it to the request object.
  4. Access Control: If no token is found or if the token is invalid, the middleware responds with a 401 Unauthorized status, preventing access to the protected route.
  • Example Code

    const jwt = require('jsonwebtoken');
    const jwtSecret = process.env.JWT_SECRET;
    
    const authMiddleware = (req, res, next) => {
      const token = req.cookies.token;
      if (!token) {
        return res.status(401).redirect('/unauthorized');
      }
      try {
        const decoded = jwt.verify(token, jwtSecret);
        req.userId = decoded.userId;
        next();
      } catch (err) {
        console.error(err);
        return res.status(401).redirect('/unauthorized');
      }
    };

Home Page

  • View Recent Posts: The home page displays the most recent blog posts.
  • Read a Post: Click on any post title to read the full content.

Preview

Admin Dashboard

  • Access the Dashboard: Log in with your admin credentials to access the dashboard.

  • Create a New Post:

    • Steps:

      1. Navigate to the dashboard.
      2. Click on the "Add Post" button.
      3. Fill in the title and content of your new post.
      4. Click "Submit" to publish the post.
    • Code:

      // POST /add-post
      router.post('/add-post', authMiddleware, async (req, res) => {
        try {
          const newPost = new Post({
            title: req.body.title,
            body: req.body.body
          });
          await Post.create(newPost);
          res.redirect('/dashboard');
        } catch (error) {
          console.log(error);
        }
      });
  • Edit an Existing Post:

    • Steps:

      1. In the dashboard, find the post you want to edit.
      2. Click on the "Edit" button next to the post.
      3. Update the title and content as needed.
      4. Click "Update" to save the changes.
    • Code:

      // PUT /edit-post/:id
      router.put('/edit-post/:id', authMiddleware, async (req, res) => {
        try {
          await Post.findByIdAndUpdate(req.params.id, {
            title: req.body.title,
            body: req.body.body,
            updatedAt: Date.now()
          });
          res.redirect(`/edit-post/${req.params.id}`);
        } catch (error) {
          console.log(error);
        }
      });
  • Delete a Post:

    • Steps:

      1. In the dashboard, find the post you want to delete.
      2. Click on the "Delete" button next to the post.
      3. Confirm the deletion to remove the post.
    • Code:

      // DELETE /delete-post/:id
      router.delete('/delete-post/:id', authMiddleware, async (req, res) => {
        try {
          await Post.deleteOne({ _id: req.params.id });
          res.redirect('/dashboard');
        } catch (error) {
          console.log(error);
        }
      });

Search Functionality

  • Search for Posts:
    • Steps:

      1. Use the search bar located at the top of the page.
      2. Enter keywords related to the post titles or content.
      3. View the search results that match your query.
    • Code:

      // POST /search
      router.post('/search', async (req, res) => {
        try {
          const locals = {
            title: "Nodejs Blog",
            description: "Simple blog with Nodejs, express & MongoDB"
          };
          let searchTerm = req.body.searchTerm || ""; // Provide a default value
          const searchNoSpecialCharacters = searchTerm.replace(/[^a-zA-Z0-9]/g, "");
          const data = await Post.find({
            $or: [
              { title: { $regex: new RegExp(searchNoSpecialCharacters, 'i') } },
              { body: { $regex: new RegExp(searchNoSpecialCharacters, 'i') } }
            ]
          });
          res.render('search', { locals, data, currentRoute: '/search' });
        } catch (err) {
          console.error(err);
        }
      });

Preview

User Authentication

  • Admin Login:
    • Steps:

      1. Go to the admin login page.
      2. Enter your username and password.
      3. Click "Login" to access the admin dashboard.
    • Code:

      // POST /admin
      router.post('/admin', async (req, res) => {
        try {
          const { username, password } = req.body;
          const user = await User.findOne({ username });
          if (!user) {
            return res.status(401).json({ message: 'Invalid credentials' });
          }
          const isPasswordValid = await bcrypt.compare(password, user.password);
          if (!isPasswordValid) {
            return res.status(401).json({ message: 'Invalid credentials' });
          }
          const token = jwt.sign({ userId: user._id }, jwtSecret);
          res.cookie('token', token, { httpOnly: true });
          res.redirect('/dashboard');
        } catch (error) {
          console.log(error);
        }
      });