This is a REST API for a Blog created using NodeJS, ExpressJS and MongoDB. Authentication for this project was done using Passport and JWT.
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.
git clone https://github.com/wendeee/blog_API.git
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
npm run dev
field | data_type | constraints |
---|---|---|
firstname | string | required |
lastname | string | required |
string | required | |
password | string | required |
posts | objectId | referenced |
timestamps | Date | required |
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 |
field | data_type | constraints |
---|---|---|
_user | objectId | referenced |
_post | objectId | referenced |
timestamps | Date | required |
-
Route: /api/auth/signup
-
method: POST
-
👇: Body
{
"firstname": "doeey",
"lastname": "example",
"email": "[email protected]",
"password": "doeeyexample",
}
👇: Response
{
"success": true,
"message": "Signed up successfully!",
"token": {token}
}
Route: /api/auth/login method: POST
👇: Body
{
"email": "[email protected]",
"password": "doeeyexample"
}
👇: Response
{
"success": true,
"token" : {token}
}
- Route: /api/auth/forgotPassword
- Method: POST
👇: Body
{
"email": "[email protected]"
}
👇: Response
{
"status": "success",
"message": "A reset token has been sent to your email"
}
- Route: /api/auth/resetPassword/:token
- Method: PATCH
👇: Body
{
"password": "doeeynewpassword",
}
👇: Response
{
"status": "success",
"message": "Password changed successfully"
}
- 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
}
- 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
}
- 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
}
}
- 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>
- 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>
- 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
-
Twitter - @_ChinwenduE
-
Email - [email protected]
Project Link: https://github.com/wendeee/blog_API