β a wonderful Blogging API built by tobisupreme.
Requirements for the examination project
-
Users should have a first_name, last_name, email, password,
-
A user should be able to sign up and sign in into the blog app
-
Use JWT as authentication strategy and expire the token after 1 hour
-
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 blogs created
-
Logged in and not logged in users should be able to to get a published blog
-
Logged in users should be able to create a blog.
-
When a blog is created, it is in draft state
-
The owner of the blog should be able to update the state of the blog to published
-
The owner of a blog should be able to edit the blog in draft or published state
-
The owner of the blog should be able to delete the blog in draft or published state
-
The owner of the blog should be able to get a list of their blogs.
-
The endpoint should be paginated
-
It should be filterable by state
-
Blogs created should have title, description, tags, author, timestamp, state, read_count, reading_time and body.
-
The list of blogs endpoint that can be accessed by both logged in and not logged in users should be paginated:
-
default it to 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 is requested, the api should return the user information (the author) with the blog. The read_count of the blog too should be updated by 1
-
Come up with any algorithm for calculating the reading_time of the blog.
-
Write tests for all endpoints
git clone https://github.com/tobisupreme/blogolicious.git
npm install
or
yarn install
Update .env with example.env
npm run start:dev
or
yarn run start:dev
npm run test
or
yarn run test
field | data_type | constraints |
---|---|---|
username | string | required, unique |
firstName | string | required |
lastName | string | required |
string | required, unique | |
password | string | required |
articles | ref - Article |
field | data_type | constraints |
---|---|---|
title | string | required, unique |
description | string | optional |
author | ref - User | |
owner | string | |
state | string | required, default: 'draft', enum: ['draft', 'published'] |
read_count | Number | default: 0 |
reading_time | Number | |
tags | array | optional |
body | string | required |
- Route: /api/signup
- Method: POST
π Body
{
"firstName": "John",
"lastName": "Doe",
"username": "mightyjoe",
"email": "[email protected]",
"password": "Password0!"
}
π Response
{
"status": "success",
"data": {
"firstName": "John",
"lastName": "Doe",
"username": "mightyjoe",
"email": "[email protected]",
"articles": [],
"_id": "6367c296ba7522bd8561e4f6"
}
}
- Route: /api/login
- Method: POST
π Body
{
"username": "mightyjoe",
"password": "Password0!"
}
π Response
{
"token": {token},
"username": "mightyjoe",
"name": "John"
}
- Route: /api/blog
- Method: POST
- Header
- Authorization: Bearer {token}
π Body
{
"title": "The Adventures of John",
"tags": ["memoirs", "expose", "fun"],
"description": "Fun times as Johnny",
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun!"
}
π Response
{
"status": "success",
"data": {
"title": "The Adventures of John",
"description": "Fun times as Johnny",
"author": "6367c296ba7522bd8561e4f6",
"state": "draft",
"read_count": 0,
"tags": ["memoirs", "expose", "fun"],
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun!",
"_id": "6367cc2271c384885108032f",
"createdAt": "2022-11-06T15:00:50.202Z",
"updatedAt": "2022-11-06T15:00:50.202Z",
"reading_time": 1
}
}
-
Route: /api/blog
-
Method: GET
-
Header
- Authorization: Bearer {token}
- None (Accessible to unauthenticated users)
-
Query params:
-
page (default: 1)
-
size (default: 20)
-
Filters: Limit returned response by passing values to any of the following parameters:
- author
/api/blog?author=Author
- title
/api/blog?title=Title
- tags: Separate multiple values with a comma
/api/blog?tags=sql,database
-
Sort: Sort returned response by passing values matching the fields in the blog to the
orderby
parameter. To sort in descending order, add a-
prefix. Separate multiple values with a commaAcceptable values include:
- author
- title
- read_count
- reading_time
/api/blog?orderby=title,-read_count
-
Fields: Set the fields to display in the returned response by passing values matching the fields in the blog to the
fields
parameter. To omit any fields, add a-
prefix. Separate multiple values with a commaDefault fields are
title
andtags
. Acceptable values include:- author
- title
- body
- read_count
- reading_time
/api/blog?fields=body,-tags,reading_time
-
-
Route: /api/blog/p
-
Method: GET
-
Header
- Authorization: Bearer {token}
-
Query params:
-
page (default: 1)
-
size (default: 20)
-
Filters: Limit returned response by passing values to any of the following parameters:
- state
/api/blog?state=draft
/api/blog?state=published
- title
/api/blog?title=Title
- tags: Separate multiple values with a comma
/api/blog?tags=sql,database
-
Sort: Sort returned response by passing values matching the fields in the blog to the
orderby
parameter. To sort in descending order, add a-
prefix. Separate multiple values with a commaAcceptable values include:
- title
- read_count
- reading_time
/api/blog?orderby=title,-read_count
-
Fields: Set the fields to display in the returned response by passing values matching the fields in the blog to the
fields
parameter. To omit any fields, add a-
prefix. Separate multiple values with a commaDefault fields are
title
andtags
. Acceptable values include:- author
- title
- body
- read_count
- reading_time
/api/blog?fields=body,-tags,reading_time
-
- Route: /api/blog/:articleId
- Method: GET
- Header
- Authorization: Bearer {token}
- None (Published blogs accessible to unauthenticated users)
π Response
{
"status": "success",
"data": {
"_id": "6367cc2271c384885108032f",
"title": "The Adventures of John",
"description": "Fun times as Johnny",
"author": {
"_id": "6367c296ba7522bd8561e4f6",
"username": "mightyjoe"
},
"state": "published",
"read_count": 1,
"tags": [
"memoirs",
"expose"
],
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun! A sailor went to sea to see what he could see but all that he could see was the bottom of the deep blue sea.",
"createdAt": "2022-11-06T15:00:50.202Z",
"updatedAt": "2022-11-06T19:38:16.100Z",
"reading_time": 1
}
}
- Route: /api/blog/:articleId
- Method: PATCH
- Header
- Authorization: Bearer {token}
π Body
{
"state": "published"
}
π Response
{
"status": "success",
"data": {
"_id": "6367cc2271c384885108032f",
"title": "The Adventures of John",
"description": "Fun times as Johnny",
"author": "6367c296ba7522bd8561e4f6",
"state": "published",
"read_count": 0,
"tags": ["memoirs", "expose", "fun"],
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun!",
"createdAt": "2022-11-06T15:00:50.202Z",
"updatedAt": "2022-11-06T16:17:45.137Z",
"reading_time": 1
}
}
- Route: /api/blog/:articleId
- Method: PUT
- Header
- Authorization: Bearer {token}
π Body
{
"tags": ["memoirs", "expose"],
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun! A sailor went to sea to see what he could see but all that he could see was the bottom of the deep blue sea."
}
π Response
{
"status": "success",
"data": {
"_id": "6367cc2271c384885108032f",
"title": "The Adventures of John",
"description": "Fun times as Johnny",
"author": "6367c296ba7522bd8561e4f6",
"state": "published",
"read_count": 0,
"tags": ["memoirs", "expose"],
"body": "A very fun article that is long enough to be fun, and short enough to be ..fun! A sailor went to sea to see what he could see but all that he could see was the bottom of the deep blue sea.",
"createdAt": "2022-11-06T15:00:50.202Z",
"updatedAt": "2022-11-06T16:22:29.326Z",
"reading_time": 1
}
}
- Route: /api/blog/:articleId
- Method: DELETE
- Header
- Authorization: Bearer {token}
While building this project, I learned about:
- Test Driven Development
- Testing the backend
- Database Modelling
- Database Management
- Debugging
- User Authentication
- User Authorization
- Documentation
Distributed under the MIT License. See LICENSE for more information.
- Twitter - @tobisupreme
- email - [email protected]
Project Link: Blogolicious
This project was made possible by: