Skip to content

A Blog REST API (with JWT and Passport authentication) using NodeJS, ExpressJS and MongoDB

Notifications You must be signed in to change notification settings

wendeee/blog_API

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

A Backend API for Blogging Platform

This is a REST API for a Blog created using NodeJS, ExpressJS and MongoDB. Authentication for this project was done using Passport and JWT.


Contributors Forks Stargazers Issues Linkedin Badge Twitter Badge AltSchool Badge


Technologies used

NodeJS Express.js MongoDB JWT


Requirements

The following are the requirements for this project πŸ‘‡:
  • A user should be able to sign up and login into the blog app.

  • Users should have a firstname, lastname, email, password, (and any other attributes that can be stored about the user).

  • User login should be authenticated using JWT and token should expire after 1 hr

  • A blog can be in two states; draft and published.

  • Logged in and not logged in users should be able to get a list of published blog posts.

  • Logged in and not logged in users should be able to to get a published blog post.

  • Logged in users should be able to create a blog post

  • A created blog post should be in draft state

  • The author of the blog should be able to update the state of the blog post to published.

  • The author of a blog post should be able to edit blog post (in draft or published state) created by him.

  • The author of a blog post should be able to delete a blog post (in draft or published state) created by him.

  • An author of should be able to get a list of all their created blog posts.

    • The endpoint should be paginated
    • Blog posts should be filterable by state
  • Blog post created should have title, description, tags, author, timestamp, state, read_count, reading_time and body.

  • The list of blog post endpoint that can be accessed by both logged in and not logged in users should be paginated.

    • It should have a default of 20 blogs per page.
    • It should also be searchable by author, title and tags.
    • It should also be orderable by read_count, reading_time and timestamp.
  • When a single blog post is requested, the api should return the user information(the author) with the blog. The readcount of the blog too should be updated by 1.

  • Implement a function that calculates the reading time of each blog.



Development

Prerequisites

Clone this repo

 git clone https://github.com/wendeee/blog_API.git

Install project dependencies

npm install

Update .env with example.env

Sign up on mailtrap for free to get the following detailsπŸ‘‡:

- EMAIL_USERNAME
- EMAIL_PASSWORD
- EMAIL_HOST
- EMAIL_PORT

Run development server

npm run dev

Models


User

field data_type constraints
firstname string required
lastname string required
email string required
password string required
posts objectId referenced
timestamps Date required

Post

field data_type constraints
title string required
description string required
tags array optional
readCount number added dynamically
author string required
state string required, enum: ['draft', 'published']
body string required
readingTime String added dynamically
likes Number added dynamically
timestamps Date required

LikePost

field data_type constraints
_user objectId referenced
_post objectId referenced
timestamps Date required

API Endpoints


Base URL

USERS

Register/Sign up a user

  • Route: /api/auth/signup

  • method: POST

  • πŸ‘‡: Body

{

  "firstname": "doeey",
  "lastname": "example",
   "email": "doeey@example.com",
   "password": "doeeyexample",
}

πŸ‘‡: Response

{
     "success": true,
    "message": "Signed up successfully!",
    "token": {token}
}

Login/Sign in a user

Route: /api/auth/login method: POST

πŸ‘‡: Body

{
    "email": "doeey@example.com",
   "password": "doeeyexample"
}

πŸ‘‡: Response

{
    "success": true,
    "token" : {token}
}

Forgot Password

  • Route: /api/auth/forgotPassword
  • Method: POST

πŸ‘‡: Body

{
    "email": "doeey@example.com"
}

πŸ‘‡: Response

{
    "status": "success",
    "message": "A reset token has been sent to your email"
}

Reset Password

  • Route: /api/auth/resetPassword/:token
  • Method: PATCH

πŸ‘‡: Body

{
    "password": "doeeynewpassword",
}

πŸ‘‡: Response

{
   "status": "success",
    "message": "Password changed successfully"
}

POSTS

Create a Post

  • Route: /api/v1/blogs
  • Method: POST
  • Header
  • Authorization: Bearer {token}

πŸ‘‡: Body

{
    "title": "Getting started with NodeJS",
    "description": "blogpost on NodeJS",
    "tags": "NodeJS",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus"
}

πŸ‘‡: Response

{
    "title": "Getting started with NodeJS",
    "description": "blogpost on NodeJS",
    "tags": [
        "NodeJS"
    ],
    "readCount": 0,
    "author": "doeey example",
    "authorId": "63a45e5b48e3b52bb6153744",
    "state": "draft",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus",
    "readingTime": "1mins",
    "likes": 0,
    "_id": "63a4621048e3b52bb6153748",
    "createdAt": "2022-12-22T13:56:32.559Z",
    "updatedAt": "2022-12-22T13:56:32.559Z",
    "__v": 0
}

Update a Post

  • Route: /api/v1/blogs/:postId
  • Method: PUT
  • Header
  • Authorization: Bearer {token}

πŸ‘‡: Body

{
  "state": "published"
}

πŸ‘‡: Response

{
    "_id": "63a4621048e3b52bb6153748",
    "title": "Getting started with NodeJS",
    "description": "blogpost on NodeJS",
    "tags": [
        "NodeJS"
    ],
    "readCount": 0,
    "author": "doeey example",
    "authorId": "63a45e5b48e3b52bb6153744",
    "state": "published",
    "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus",
    "readingTime": "1mins",
    "likes": 0,
    "createdAt": "2022-12-22T13:56:32.559Z",
    "updatedAt": "2022-12-22T13:59:55.005Z",
    "__v": 0
}

Like(and unlike) a Post

  • Route: /api/v1/blogs/:postId/like
  • Method: PATCH
  • Header
  • Authorization: Bearer {token}

πŸ‘‡: Response

{
    "status": "success",
    "message": "You liked this post!",
    "post": {
        "_id": "63a4621048e3b52bb6153748",
        "title": "Getting started with NodeJS",
        "description": "blogpost on NodeJS",
        "tags": [
            "NodeJS"
        ],
        "readCount": 0,
        "author": "doeey example",
        "authorId": "63a45e5b48e3b52bb6153744",
        "state": "published",
        "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus",
        "readingTime": "1mins",
        "likes": 1,
        "createdAt": "2022-12-22T13:56:32.559Z",
        "updatedAt": "2022-12-22T14:05:07.468Z",
        "__v": 0
    }
}

Get all Posts (published)

  • Route: /api/v1/blogs
  • Method: GET

πŸ‘‡: Response

{
    "totalBlogs": 3,
    "posts": [
        {
            "_id": "63a4621048e3b52bb6153748",
            "title": "Getting started with NodeJS",
            "description": "blogpost on NodeJS",
            "tags": [
                "NodeJS"
            ],
            "readCount": 0,
            "author": "doeey example",
            "authorId": "63a45e5b48e3b52bb6153744",
            "state": "published",
            "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus",
            "readingTime": "1mins",
            "likes": 1,
            "createdAt": "2022-12-22T13:56:32.559Z",
            "updatedAt": "2022-12-23T01:52:35.836Z",
            "__v": 0
        },
        {
            "_id": "63a50edfc0ce8d15aab286ce",
            "title": "How to know your zodiac sign",
            "description": "about zodiac",
            "tags": [
                "zodiac"
            ],
            "readCount": 0,
            "author": "Leanne Graham Graham",
            "authorId": "63a44513d9c36e45528f199e",
            "state": "published",
            "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis.s",
            "readingTime": "1mins",
            "likes": 0,
            "createdAt": "2022-12-23T02:13:51.677Z",
            "updatedAt": "2022-12-23T02:14:39.915Z",
            "__v": 0
        },
        {
            "_id": "63a50b30b31bec4edd9946cf",
            "title": "Getting started with ExpressJs",
            "description": "blogpost on ExpressJs",
            "tags": [
                "ExpressJs"
            ],
            "readCount": 1,
            "author": "doeey example",
            "authorId": "63a45e5b48e3b52bb6153744",
            "state": "published",
            "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis. e in.\n\nDuis tristique sollicitudin nibh sit amet commodo nulla facilisi. Ultricies lacus sed turpis tincidunt id aliquet risus. Tortor vitae purus faucibus ornare sus",
            "readingTime": "1mins",
            "likes": 0,
            "createdAt": "2022-12-23T01:58:08.052Z",
            "updatedAt": "2022-12-23T01:59:45.706Z",
            "__v": 0
        }
    ]
}
  • Query Params:
    • page: default(1)
    • limit: default(20 i.e 20 blog post per page)
    • filter query: You can filter search using the following queries:
      • author
      /api/v1/blogs?author=<authorName>
      
      • title
      /api/v1/blogs?title=<titleOfPost>
      
      • tags
       /api/v1/blogs?tags=<tags>
      
    • orderBy: Sort using the orderBy query parameter (default value: readCount).Multiple values seperated with a comma can be passed as well.
      /api/v1/blogs?orderBy=<title>,<readCount>,<readingTime>
      
    • order: By default, response is returned in ascending order. To return in descending order, use order=desc
    /api/v1/blogs?orderBy=<title>,<readCount>,<readingTime>&order=<desc>|<asc>
    

AUTHOR'S ENDPOINT

Get all post (both publshed and in draft state) for author

  • Route: /api/v1/author/blogs
  • Method: GET
  • Header
  • Authorization: Bearer {token}

πŸ‘‡: Response

{
    "page": 1,
    "numOfPosts": 2,
    "posts": [
        {
            "_id": "63a50edfc0ce8d15aab286ce",
            "title": "How to know your zodiac sign",
            "description": "about zodiac",
            "tags": [
                "zodiac"
            ],
            "readCount": 0,
            "author": "Leanne Graham Graham",
            "authorId": "63a44513d9c36e45528f199e",
            "state": "published",
            "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis.s",
            "readingTime": "1mins",
            "likes": 0,
            "createdAt": "2022-12-23T02:13:51.677Z",
            "updatedAt": "2022-12-23T02:14:39.915Z",
            "__v": 0
        },
        {
            "_id": "63a51b1fc0ce8d15aab286f1",
            "title": "What is Testing",
            "description": "unit testing",
            "tags": [
                "testing"
            ],
            "readCount": 0,
            "author": "Leanne Graham Graham",
            "authorId": "63a44513d9c36e45528f199e",
            "state": "draft",
            "body": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \ns. Commodo sed egestas egestas fringilla phasellus faucibus scelerisque eleifend donec. Mi ipsum faucibus vitae aliquet nec ullamcorper sit. Neque sodales ut etiam sit amet nisl purus in mollis.s",
            "readingTime": "1mins",
            "likes": 0,
            "createdAt": "2022-12-23T03:06:07.827Z",
            "updatedAt": "2022-12-23T03:06:07.827Z",
            "__v": 0
        }
    ]
}
  • Query Params:
    • page: default(1)
    • limit: default(10 i.e 10 blog post per page)
    • filter query: You can filter search using the following queries:
      • state
      /api/v1/blogs?state=<draft | published>
      


Lessons I learned while working on this:

  • How to model data
  • Mongoose Database Schema Design
  • User authentication and authorization using JWT and Passport
  • How to add pagination and filtering features to an API
  • How to query mongoDB using mongoose ODM

Contact

Project Link: https://github.com/wendeee/blog_API

About

A Blog REST API (with JWT and Passport authentication) using NodeJS, ExpressJS and MongoDB

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published