/blog-management-system

Blog management system using flask and nextjs

Primary LanguagePython

Blog Management System

This project was last project for the Udacity Full Stack Developer Nanodegree Course.

The tech stack of this project is:

Prerequisite

  • Python3 and pip
  • Nodejs (version above 10.x.x) and npm
  • PostgresSQL

Project Installation

Authentication

Project uses google auth for login/sign up. There are 2 role based permission.

  • writer
  • admin

By default user will be given writer role on signup. You can change the role from the databse by changing role column in the users table.

Create you oauth client id by visiting google console.

  1. Create new project
  2. Go to credentials
  3. Create OAuth 2.0 Client IDs
  4. Replace the client id in /backend/app/auth/func.py and in /frontend/pages/login.js

Backend

Create .env file in backend folder with the following fields. Replace the value according to your environment.

DATABASE=postgres
DB_USER=db_user_name
DB_PASSWORD=db_password
HOST_ADDRESS=localhost:5432
DB_NAME=db_name
cd Backend
# create virtual environment
virtualenv venv
# install packages
pip install -r requirements.txt
# create db
createdb db_name

Starting the project

Development Server

export FLASK_APP=manage
export FLASK_ENV=development

# run migrations once
flask db upgrade

flask run

Production Server

gunicorn -w 4 manage:app

Frontend

cd frontend
# install packages
yarn install

Running the project

Development Server

yarn run dev

Production Server

yarn run start

API Documentation

API follows Restful API convenctions.

Request status will be indicated by status code and success value in the response body.

Endpoints

/login [POST] Takes Authorization header containing token generated by the google signin. It will verify the jwt token and if successful it will return jwtToken. If the user is logging in for the first time, user info will be added to the table (name, email, profile pic).

{
    "success": true,
    "token": "token",
    "userInfo": {
        "name": "name",
        "email": "email",
        "picture": "picture"
    }
}

/posts [GET]

Returns posts based on the query parameter type

  • type -> enum (featured, latest) featured - returns featured posts containing Post.is_featured = True latest - returns posts by sorted Post.created_at
  • limit -> int default - 10
{
    "success": true,
    "posts": [
        {
            "id": "id",
            "title": "title",
            "body": "body[:150]",
            "url_slug": "url_slug",
            "created_at": "created_at",
            "updated_at": "updated_at",
            "is_publish": "is_publish",
            "is_featured": "is_featured",
            "user_id": "user_id",
        },
        ...
    ]
}

/post [GET]

Returns posts based on the query parameter url

{
    "sucesss": true,
    "post": {
        "id": "id",
        "title": "title",
        "body": "body[:150]",
        "url_slug": "url_slug",
        "created_at": "created_at",
        "updated_at": "updated_at",
        "is_publish": "is_publish",
        "is_featured": "is_featured",
        "user_id": "user_id",
    },
    "writer": {
        "name": "name",
        "email": "email",
        "picture": "picture",
        "bio": "bio",
        "role": "role",
    }
}

/post [POST]

Adds new post. Must contain Authorization jwt token.

// Request Body
{
    "title": "title",
    "body": "body[:150]",
    "url_slug": "url_slug",
    "is_publish": "is_publish",
}
// Response Body
{
    "sucesss": true,
}

/post [PATCH]

Updates existing post. Must contain Authorization jwt token.

// Request Body
{
    "id": 1,
    "title": "title",
    "body": "body",
    "url_slug": "url_slug",
    "is_publish": "is_publish",
}
// Response Body
{
    "sucesss": true,
}

/post/<post_id> [DELETE]

Deletes post with post id equal to <post_id>. Must contain Authorization jwt token.

{
    "sucesss": true,
}