diff options
author | Rasmus Luha <rasmus.luha@gmail.com> | 2022-02-06 13:41:11 +0200 |
---|---|---|
committer | Rasmus Luha <rasmus.luha@gmail.com> | 2022-02-06 13:41:11 +0200 |
commit | 6a6afdbe72c626b01245c9372c9d10be79789bb0 (patch) | |
tree | cfdb5aea7538296bad0105c813fce4cd33c19ef5 /Projekt/app | |
parent | 5e19a0569288de21365c61b0db78639880732dd0 (diff) |
restrucurring the stucture of the folderstruture --> structure
Diffstat (limited to 'Projekt/app')
-rw-r--r-- | Projekt/app/__init__.py | 0 | ||||
-rw-r--r-- | Projekt/app/config.py | 16 | ||||
-rw-r--r-- | Projekt/app/database.py | 38 | ||||
-rw-r--r-- | Projekt/app/main.py | 17 | ||||
-rw-r--r-- | Projekt/app/models.py | 31 | ||||
-rw-r--r-- | Projekt/app/oauth2.py | 49 | ||||
-rw-r--r-- | Projekt/app/routers/auth.py | 22 | ||||
-rw-r--r-- | Projekt/app/routers/post.py | 102 | ||||
-rw-r--r-- | Projekt/app/routers/user.py | 27 | ||||
-rw-r--r-- | Projekt/app/routers/vote.py | 45 | ||||
-rw-r--r-- | Projekt/app/schemas.py | 61 | ||||
-rw-r--r-- | Projekt/app/utils.py | 9 |
12 files changed, 0 insertions, 417 deletions
diff --git a/Projekt/app/__init__.py b/Projekt/app/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/Projekt/app/__init__.py +++ /dev/null diff --git a/Projekt/app/config.py b/Projekt/app/config.py deleted file mode 100644 index d7f622d..0000000 --- a/Projekt/app/config.py +++ /dev/null @@ -1,16 +0,0 @@ -from pydantic import BaseSettings - -class Settings(BaseSettings): - database_hostname: str - database_port: str - database_password: str - database_name: str - database_username: str - secret_key: str - algorithm: str - access_token_expire_minutes: int - - class Config: - env_file = ".env" - -settings = Settings() diff --git a/Projekt/app/database.py b/Projekt/app/database.py deleted file mode 100644 index 1abafa0..0000000 --- a/Projekt/app/database.py +++ /dev/null @@ -1,38 +0,0 @@ -from sqlalchemy import create_engine # Copied imports from fastapi sqlalchemy docs. -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -from psycopg2.extras import RealDictCursor -from time import sleep -import psycopg2 #Library to connect to postgres -from .config import settings - -SQLALCHEMY_DATABASE_URL = f'postgresql://{settings.database_username}:{settings.database_password}@{settings.database_hostname}:{settings.database_port}/{settings.database_name}' - - -engine = create_engine(SQLALCHEMY_DATABASE_URL) - -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) -Base = declarative_base() - -# Dependency -def get_db(): - db = SessionLocal() - try: - yield db - finally: - db.close() - - -# Setting connection with DataBase -# PS: thats only for reference --> kautad nüüd ju hoopiki sqlalchemyt db sessioniks. Ülal - -#while True: -# try: -# conn = psycopg2.connect(host='localhost', database='fastapi', user='postgres', password='password123', cursor_factory = RealDictCursor)#CursorFactory minig library teema, no matter::prg pole password -# cursor = conn.cursor() -# print("DataBase Connection Was a Huge and Massive Success!") -# break -# except Exception as error: -# print("Connecting to database failed") -# print("error was: ", error) -# sleep(3) diff --git a/Projekt/app/main.py b/Projekt/app/main.py deleted file mode 100644 index 87db9d0..0000000 --- a/Projekt/app/main.py +++ /dev/null @@ -1,17 +0,0 @@ -from fastapi import FastAPI -from . import models -from .database import engine, SessionLocal -from .routers import post, user, auth, vote -from .config import settings - -models.Base.metadata.create_all(bind=engine) -app = FastAPI() - -app.include_router(post.router) -app.include_router(user.router) -app.include_router(auth.router) -app.include_router(vote.router) - -@app.get("/") -async def root(): - return {"message" : "Hellow piipl"} diff --git a/Projekt/app/models.py b/Projekt/app/models.py deleted file mode 100644 index 97d1e35..0000000 --- a/Projekt/app/models.py +++ /dev/null @@ -1,31 +0,0 @@ -from sqlalchemy import Column, Integer, String, Boolean, ForeignKey -from sqlalchemy.orm import relationship -from sqlalchemy.sql.expression import text -from sqlalchemy.sql.sqltypes import TIMESTAMP -from .database import Base - -class Post(Base): - __tablename__= "posts" - - id = Column(Integer, primary_key=True, nullable=False) - title = Column(String, nullable=False) - content = Column(String, nullable=False) - published = Column(Boolean, server_default="true", nullable=False) - created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=text('now()') ) - - owner_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False) - owner = relationship("User") #Fetcib owner_id põhjal( see foreign key) vastava Posti teinud User callsi useri - -class User(Base): - __tablename__ = "users" - - id = Column(Integer, primary_key=True, nullable=False) - email = Column(String, nullable=False, unique = True) - password = Column(String, nullable=False) - created_at = Column(TIMESTAMP(timezone=True), nullable=False, server_default=text('now()') ) - - -class Vote(Base): - __tablename__ = "votes" - user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), primary_key=True) - post_id = Column(Integer, ForeignKey("posts.id", ondelete="CASCADE"), primary_key=True) diff --git a/Projekt/app/oauth2.py b/Projekt/app/oauth2.py deleted file mode 100644 index f381f97..0000000 --- a/Projekt/app/oauth2.py +++ /dev/null @@ -1,49 +0,0 @@ -from fastapi import Depends, status, HTTPException -from jose import JWTError, jwt -from datetime import datetime, timedelta -from sqlalchemy.orm import Session -from . import schemas, database, models -from fastapi.security import OAuth2PasswordBearer -from .config import settings - -oaut2_scheme = OAuth2PasswordBearer(tokenUrl="login") - -#Secrete_Key -#Algorütm -#Säilivusaeg, expiration time - -SECRET_KEY = settings.secret_key -ALGORITHM = settings.algorithm -ACCESS_TOKEN_EXPIRE_MINUTES = settings.access_token_expire_minutes - -def create_access_token(data: dict): - to_encode = data.copy() - - expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES) - to_encode.update( {"exp" : expire} ) - - encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM) - return encoded_jwt - -def verify_access_token(token: str, credentials_exception): - - try: - payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM]) #Decodeme tokeni - id: str = payload.get("user_id") # Ekstraktime tokenist id - if id is None: - raise credentials_exception - token_data = schemas.TokenData(id=id) - except JWTError: - raise credentials_exception - - return token_data - - -def get_current_user( token: str = Depends(oaut2_scheme), db: Session = Depends(database.get_db)): - credentials_exception = HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, - detail=f"Could not validate credentials", headers={"WWW-Authenticate": "Bearer"} ) - - token = verify_access_token(token, credentials_exception) - user = db.query(models.User).filter(models.User.id == token.id).first() - - return user diff --git a/Projekt/app/routers/auth.py b/Projekt/app/routers/auth.py deleted file mode 100644 index 30668cf..0000000 --- a/Projekt/app/routers/auth.py +++ /dev/null @@ -1,22 +0,0 @@ -from fastapi import APIRouter, Depends, status, HTTPException, Response -from fastapi.security.oauth2 import OAuth2PasswordRequestForm -from sqlalchemy.orm import Session -from .. import database, schemas, models, utils, oauth2 - -router = APIRouter(tags = ["Authentication"]) - -@router.post("/login", response_model = schemas.Token) -def login(user_credentials: OAuth2PasswordRequestForm = Depends(), db: Session = Depends(database.get_db)): #OAuth2Password... --> nüüd ei oota api requesti bodysse email, password vaid hoopis form-data. - - user = db.query(models.User).filter(models.User.email == user_credentials.username).first() - - if not user: - raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Invalid Credentials unfortunatuun") - - if not utils.verify(user_credentials.password, user.password): - raise HTTPException(status_code=status.HTTP_403_FORBIDDEN , detail="Invalid Credentials unfortunatuun") - - #Create and retrn token - access_token = oauth2.create_access_token(data = {"user_id":user.id}) - - return {"access_token" : access_token, "token_type" : "bearer" } diff --git a/Projekt/app/routers/post.py b/Projekt/app/routers/post.py deleted file mode 100644 index ce1c11d..0000000 --- a/Projekt/app/routers/post.py +++ /dev/null @@ -1,102 +0,0 @@ -from fastapi import FastAPI, Response, status, HTTPException, Depends, APIRouter -from .. import models, schemas, oauth2 -from sqlalchemy import func -from sqlalchemy.orm import Session -from ..database import get_db -from typing import List, Optional - -router = APIRouter(prefix="/posts", tags=["Posts"]) - - -@router.get("/", response_model=List[schemas.PostOut]) # Siin List (from typing lib), sest võttame mitu posti, teistes vaid 1 -async def get_posts(db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user) - ,limit: int = 10, skip: int = 0, search: Optional[str] = ""): - - #cursor.execute(""" SELECT * FROM posts """) - #posts = cursor.fetchall() - - - #Lots of query parameter stuff here, kinda testing atm. - #posts = db.query(models.Post).filter(models.Post.title.contains(search)).limit(limit).offset(skip).all() - - posts = db.query(models.Post, func.count(models.Vote.post_id).label("votes") ).join(models.Vote, - models.Vote.post_id == models.Post.id, isouter=True).group_by(models.Post.id).filter(models.Post.title.contains(search)).limit(limit).offset(skip).all() - - return posts #FastAPI converts automaticaly into json types stuff - - -@router.get("/{id}", response_model=schemas.PostOut) #ID is called "path parameter" , could name it dingdong if wanted. Its just like a argument/variable -async def get_post(id: int, db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user)): #id: int > Et url ei oleks "afasdfasdfasf" <-- Siis viskab errori. Response imported from FastAPI - #cursor.execute(""" SELECT * FROM posts WHERE id = %s RETURNING *""", (str(id))) - #post = cursor.fetchone() - #post = db.query(models.Post).filter(models.Post.id == id).first() - - post = db.query(models.Post, func.count(models.Vote.post_id).label("votes") ).join(models.Vote, - models.Vote.post_id == models.Post.id, isouter=True).group_by(models.Post.id).filter(models.Post.id == id).first() - - - if not post: - raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, - detail=f"Post with id: {id} was not found") - return post - - -@router.post("/", status_code = status.HTTP_201_CREATED, response_model=schemas.Post) # Create puhul default kood 201. Miks mitte lihtsalt "201", miks status.blabblalba -async def create_posts(post: schemas.PostCreate,db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user) ): # Ekstraktib body read dictiks "pay.. - #cursor.execute(""" INSERT INTO posts(title, content, published) VALUES (%s, %s, %s) - #RETURNING * """, (post.title, post.content, post.published) ) - #new_post = cursor.fetchone() - #conn.commit() - print(current_user.email) - - #new_post = models.Post(title=post.title, content=post.content, published=post.published) - new_post = models.Post(owner_id=current_user.id, **post.dict()) # Sama mis ülal, ilusamini - - - db.add(new_post) - db.commit() # not sure why have to add+commit, but hey - db.refresh(new_post) # sama mis SQL: "RESPONDING *" - return new_post - -@router.put("/{id}") -def update_post(id: int, post: schemas.PostCreate, db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user) ): - - post_query = db.query(models.Post).filter(models.Post.id == id) - posters = post_query.first() - - if posters == None: - raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, detail = f"post with id: {id} was not found") - - - if posters.owner_id != current_user.id: - raise HTTPException(status_code = status.HTTP_403_FORBIDDEN, - detail=f"Not authorized duuud") - - post_query.update(post.dict(), synchronize_session=False) - - db.commit() - - return post_query.first() - - -@router.delete("/{id}", status_code = status.HTTP_204_NO_CONTENT) -async def delete_post(id: int, db: Session = Depends(get_db), current_user: int = Depends(oauth2.get_current_user) ): - #cursor.execute(""" DELETE FROM posts WHERE id = %s RETURNING * """, (str(id),)) - #deleted_post = cursor.fetchone() - #conn.commit() - - post_query = db.query(models.Post).filter(models.Post.id == id) - post = post_query.first() - - if post == None: - raise HTTPException(status_code = status.HTTP_404_NOT_FOUND, - detail=f"Post with id: {id} was not found") - - if post.owner_id != current_user.id: - raise HTTPException(status_code = status.HTTP_403_FORBIDDEN, - detail=f"Not authorized duuud") - - post_query.delete(synchronize_session=False) # Ei tea mis teeb, fastapi docs ütles et panna, vist ka default - db.commit() - - return Response(status_code = status.HTTP_204_NO_CONTENT) diff --git a/Projekt/app/routers/user.py b/Projekt/app/routers/user.py deleted file mode 100644 index 1afe06e..0000000 --- a/Projekt/app/routers/user.py +++ /dev/null @@ -1,27 +0,0 @@ -from fastapi import FastAPI, Response, status, HTTPException, Depends, APIRouter -from .. import models, schemas, utils -from sqlalchemy.orm import Session -from ..database import get_db - -router = APIRouter(prefix = "/users", tags=["Users"]) - -@router.post("/", status_code=status.HTTP_201_CREATED, response_model=schemas.UserOut) -def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)): - #hash the password <-> user.password - hashed_password= utils.hash(user.password) - user.password = hashed_password - - new_user = models.User(**user.dict()) - db.add(new_user) - db.commit() # not sure why have to add+commit, but hey - db.refresh(new_user) # sama mis SQL: "RESPONDING *" - return new_user - -@router.get("/{id}", response_model=schemas.UserOut) -def get_user(id: int, db: Session = Depends(get_db)): - user = db.query(models.User).filter(models.User.id == id).first() - - if not user: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=f"User with id: {id} not found") - - return user diff --git a/Projekt/app/routers/vote.py b/Projekt/app/routers/vote.py deleted file mode 100644 index af17b88..0000000 --- a/Projekt/app/routers/vote.py +++ /dev/null @@ -1,45 +0,0 @@ -from fastapi import APIRouter, Depends, status, HTTPException, Response -from sqlalchemy.orm import Session -from .. import schemas, database, models, oauth2 - -router = APIRouter( - prefix="/vote", - tags=["vote"] -) - - -@router.post("/", status_code=status.HTTP_201_CREATED) -def vote(vote: schemas.Vote, db: Session = Depends(database.get_db) - , current_user: int = Depends(oauth2.get_current_user) ): - - post = db.query(models.Post).filter(models.Post.id == vote.post_id).first() # Cheki seda, et ei proovi likeda posti mida ei eksisteeri - if not post: - raise HTTPException(status_code=status.HTTP404_NOT_FOUND, - detail=f"The post with id {vote.id} that you are trying to like doesn't exsits") - - - vote_query = db.query(models.Vote).filter(models.Vote.post_id == vote.post_id, - models.Vote.user_id == current_user.id) - found_vote=vote_query.first() # kui oled juba posti likenud, siis filter leiab, kui ei ole, siis ei leia - - if (vote.dir == 1): - if found_vote: - raise HTTPException(status_code=status.HTTP_409_CONFLICT, - detail=f"user {current_user.email} has alreadey liked the post {vote.post_id}") - new_vote = models.Vote(post_id = vote.post_id, user_id = current_user.id) - db.add(new_vote) - db.commit() - return {"Message":"Successfully liked Post"} - else: - if not found_vote: - raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, - detail=f"user {current_user.email} has not liked the post {vote.post_id}") - vote_query.delete(synchronize_session=False) - db.commit() - - return {"Message":"Succesfulle Unliked the Post"} - - - - - diff --git a/Projekt/app/schemas.py b/Projekt/app/schemas.py deleted file mode 100644 index 439722c..0000000 --- a/Projekt/app/schemas.py +++ /dev/null @@ -1,61 +0,0 @@ -from pydantic import BaseModel, EmailStr -from pydantic.types import conint -from datetime import datetime -from typing import Optional - -class PostBase(BaseModel): - title: str - content: str - published: bool = True # Default True - -class PostCreate(PostBase): - pass - -# User Stuff - -class UserCreate(BaseModel): - email: EmailStr #Selleks vaja emaild-validator lib, mis tuli pip install fastapi[all]-iga koos. - password: str - -class UserOut(BaseModel): - id: int - email: EmailStr - created_at: datetime - - class Config: - orm_mode = True - - -class UserLogin(BaseModel): - email: EmailStr - password: str - - -class Token(BaseModel): - access_token: str - token_type: str - -class TokenData(BaseModel): - id: Optional[str] = None - - -## Response - -class Post(PostBase): - id: int - created_at: datetime - owner_id: int - owner: UserOut # Class alt poolt - see skeem, mille mis kehtib ka Get Useri puhul. - - class Config: # Selleks, et pydantic oskaks lugeda sqlalchemy type modelit mida talle et antakse - orm_mode = True - -class PostOut(BaseModel): - Post: Post - votes: int - - -class Vote(BaseModel): - post_id: int - dir: conint(le=1) #int that can be only 0 or 1 (and also negative, but that should be fine) - diff --git a/Projekt/app/utils.py b/Projekt/app/utils.py deleted file mode 100644 index 3cd58bf..0000000 --- a/Projekt/app/utils.py +++ /dev/null @@ -1,9 +0,0 @@ - -from passlib.context import CryptContext # passwordide hashimise jaoks - -pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") -def hash(password: str): - return pwd_context.hash(password) - -def verify(plain_password, hashed_password): - return pwd_context.verify(plain_password, hashed_password) |