├── blog ├── blog.db ├── __init__.py ├── models │ ├── __init__.py │ ├── user.py │ └── blog.py ├── utils │ ├── __init__.py │ └── hashing.py ├── routers │ ├── __init__.py │ ├── authentication.py │ ├── user.py │ └── blog.py ├── database.py ├── main.py ├── OAuth2.py ├── schemas.py └── repository │ ├── user.py │ ├── blog.py │ └── auth.py ├── .gitignore ├── blog.db ├── images └── screenshot1.png ├── requirements.txt └── README.md /blog/blog.db: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/utils/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /blog/routers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | env 3 | blog/.DS_Store -------------------------------------------------------------------------------- /blog.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkey531/blogs-app-fastapi/HEAD/blog.db -------------------------------------------------------------------------------- /images/screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkey531/blogs-app-fastapi/HEAD/images/screenshot1.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | fastapi 2 | uvicorn 3 | sqlalchemy 4 | passlib 5 | bcrypt 6 | python-jose 7 | python-multipart -------------------------------------------------------------------------------- /blog/utils/hashing.py: -------------------------------------------------------------------------------- 1 | from passlib.context import CryptContext 2 | 3 | pswd_cxt = CryptContext(schemes=["bcrypt"], deprecated="auto") 4 | 5 | class Hashing(): 6 | def get_hashed_password(password: str): 7 | return pswd_cxt.hash(password) 8 | 9 | def verify(plain_password: str, hashed_password: str): 10 | return pswd_cxt.verify(plain_password, hashed_password) -------------------------------------------------------------------------------- /blog/models/user.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.orm import relationship 2 | from ..database import Base 3 | from sqlalchemy import Column, String 4 | 5 | class User(Base): 6 | __tablename__ = 'users' 7 | 8 | username = Column(String, primary_key= True, index=True) 9 | name = Column(String) 10 | password = Column(String) 11 | 12 | blogs = relationship('Blog', back_populates="creator") -------------------------------------------------------------------------------- /blog/database.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy import create_engine 2 | from sqlalchemy.ext.declarative import declarative_base 3 | from sqlalchemy.orm import sessionmaker 4 | 5 | DATABASE_URL = 'sqlite:///./blog.db' 6 | 7 | engine = create_engine(DATABASE_URL, connect_args = {"check_same_thread": False}) 8 | 9 | SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) 10 | 11 | Base = declarative_base() 12 | 13 | def get_db(): 14 | db = SessionLocal() 15 | try: 16 | yield db 17 | finally: 18 | db.close() -------------------------------------------------------------------------------- /blog/routers/authentication.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | from fastapi import APIRouter, Depends 3 | from sqlalchemy.orm import Session 4 | from blog import schemas 5 | from ..database import get_db 6 | from ..repository import auth as authRepository 7 | from fastapi.security import OAuth2PasswordRequestForm 8 | 9 | 10 | router = APIRouter(tags=['Authentication']) 11 | 12 | 13 | @router.post('/login') 14 | def login(login: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(get_db)): 15 | return authRepository.login(login, db) 16 | -------------------------------------------------------------------------------- /blog/models/blog.py: -------------------------------------------------------------------------------- 1 | from sqlalchemy.orm import relationship 2 | from sqlalchemy.sql.schema import ForeignKey 3 | from ..database import Base 4 | from sqlalchemy import Column, Integer, String, Boolean 5 | 6 | class Blog(Base): 7 | __tablename__ = 'blogs' 8 | 9 | id = Column(Integer, primary_key= True, index= True) 10 | title = Column(String) 11 | body = Column(String) 12 | published = Column(Boolean, default= False) 13 | 14 | username = Column(String, ForeignKey('users.username')) 15 | 16 | creator = relationship('User', back_populates="blogs") -------------------------------------------------------------------------------- /blog/main.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI 2 | from blog.models import user 3 | from .database import engine 4 | from .models import blog 5 | from blog import database 6 | from .routers import blog as blogRouter 7 | from .routers import user as userRouter 8 | from .routers import authentication as authRouter 9 | 10 | 11 | app = FastAPI() 12 | 13 | blog.Base.metadata.create_all(bind = engine) 14 | user.Base.metadata.create_all(bind = engine) 15 | 16 | get_db = database.get_db 17 | 18 | app.include_router(blogRouter.router) 19 | app.include_router(userRouter.router) 20 | app.include_router(authRouter.router) 21 | -------------------------------------------------------------------------------- /blog/routers/user.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from fastapi import APIRouter, Depends, status, HTTPException 3 | from sqlalchemy.orm import Session 4 | from blog import schemas 5 | from ..database import get_db 6 | from ..models.user import User 7 | from ..utils.hashing import Hashing 8 | from ..repository import user as userRepository 9 | 10 | 11 | router = APIRouter(tags=['Users']) 12 | 13 | @router.post('/users', status_code= status.HTTP_201_CREATED) 14 | def create_user(user: schemas.User, db: Session = Depends(get_db)): 15 | return userRepository.create(user, db) 16 | 17 | @router.get('/users/{username}', response_model=schemas.ShowUser) 18 | def get_user_by_username(username: str, db: Session = Depends(get_db)): 19 | return userRepository.get(username, db) -------------------------------------------------------------------------------- /blog/OAuth2.py: -------------------------------------------------------------------------------- 1 | from fastapi import Depends, HTTPException, status 2 | from fastapi.security import OAuth2PasswordBearer 3 | from .repository import auth as authRepository 4 | from .repository import user as userRepository 5 | from sqlalchemy.orm import Session 6 | from .database import get_db 7 | 8 | oauth2_scheme = OAuth2PasswordBearer(tokenUrl="login") 9 | 10 | async def get_current_user(token: str = Depends(oauth2_scheme), db: Session = Depends(get_db)): 11 | credentials_exception = HTTPException( 12 | status_code=status.HTTP_401_UNAUTHORIZED, 13 | detail="Could not validate credentials", 14 | headers={"WWW-Authenticate": "Bearer"}, 15 | ) 16 | token_data = authRepository.verify(token, credentials_exception) 17 | user = userRepository.get(token_data.username, db) 18 | if user is None: 19 | raise credentials_exception 20 | return user -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blogs-app-fastapi 2 | Simple Blogs app made using [FastAPI](https://github.com/tiangolo/fastapi) 3 | 4 | ## ScreenShot 5 | 6 |
8 |