β a wonderful Blogging API built as an exam project by tobisupreme, a Backend Engineering student at AltSchool Africa.
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.gitnpm installUpdate .env with example.env
npm run devnpm 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": "joe@mail.com",
"password": "Password0!"
}π Response
{
"status": "success",
"data": {
"firstName": "John",
"lastName": "Doe",
"username": "mightyjoe",
"email": "joe@mail.com",
"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/: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
}
}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 - tobi.balo@gmail.com
Project Link: Blogolicious
This project was made possible by: