Skip to content

AltSchool Backend NodeJS Second Semester Examination Project

License

Notifications You must be signed in to change notification settings

tobisupreme/blogolicious

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

60 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Contributors Forks Stargazers Issues MIT License Twitter AltSchool Badge

Blogolicious

β€” a wonderful Blogging API built by tobisupreme.

back to top

Built With:

Javascript Node.js Express.js MongoDB

back to top


Requirements

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

back to top



Development

Prerequisites

Clone this repo

git clone https://github.com/tobisupreme/blogolicious.git

Install project dependencies

npm install

or

yarn install

Update .env with example.env

Run a development server

npm run start:dev

or

yarn run start:dev

For testing, run

npm run test

or

yarn run test

Models

User

field data_type constraints
username string required, unique
firstName string required
lastName string required
email string required, unique
password string required
articles ref - Article

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

back to top


Usage

Base URL

Creating a user

  • 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"
  }
}

back to top


Logging in

  • Route: /api/login
  • Method: POST

πŸ‘‡ Body

{
  "username": "mightyjoe",
  "password": "Password0!"
}

πŸ‘‡ Response

{
  "token": {token},
  "username": "mightyjoe",
  "name": "John"
}

back to top


Create a Blog

  • 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
  }
}

back to top


Get all published blogs

  • 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 comma

      Acceptable 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 comma

      Default fields are title and tags. Acceptable values include:

      • author
      • title
      • body
      • read_count
      • reading_time
        /api/blog?fields=body,-tags,reading_time
      

back to top


Get all created blogs by authenticated user

  • 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 comma

      Acceptable 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 comma

      Default fields are title and tags. Acceptable values include:

      • author
      • title
      • body
      • read_count
      • reading_time
        /api/blog?fields=body,-tags,reading_time
      

back to top


Get specific blog

  • 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
    }
}

back to top


Update the state of a Blog

  • 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
  }
}

back to top


Update the contents of a Blog

  • 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
  }
}

back to top


Delete a Blog

  • Route: /api/blog/:articleId
  • Method: DELETE
  • Header
    • Authorization: Bearer {token}

back to top


Lessons Learned

While building this project, I learned about:

  • Test Driven Development
  • Testing the backend
  • Database Modelling
  • Database Management
  • Debugging
  • User Authentication
  • User Authorization
  • Documentation

back to top


License

Distributed under the MIT License. See LICENSE for more information.

back to top


Contact

Project Link: Blogolicious

back to top


Acknowledgements

This project was made possible by:

back to top

About

AltSchool Backend NodeJS Second Semester Examination Project

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published