Blog Management System
This project was last project for the Udacity Full Stack Developer Nanodegree Course.
The tech stack of this project is:
- Next.js (Frontend)
- Flask Backend
- PostgresSQL Databse
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.
- Create new project
- Go to credentials
- Create OAuth 2.0 Client IDs
- 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 = Truelatest
- 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,
}