This commit is contained in:
2023-07-27 20:13:13 +03:00
15 changed files with 466 additions and 41 deletions

2
back/base.py Normal file
View File

@ -0,0 +1,2 @@
from .db import Base
from .models import UserDatabase, Announcement, Trashbox

View File

@ -1,6 +1,6 @@
from typing import AsyncGenerator
from sqlalchemy import Column, Integer, String, create_engine, select
from sqlalchemy import create_engine, select
# from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.declarative import declarative_base
@ -15,7 +15,7 @@ engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(bind=engine, autoflush=True, autocommit=False, expire_on_commit=False)
SessionLocal = sessionmaker(bind=engine, autoflush=True, autocommit=False)
database = SessionLocal()
Base = declarative_base()

View File

@ -36,8 +36,22 @@ if not os.path.exists("./uploads"):
app.mount("/uploads", StaticFiles(directory = "./uploads"))
# Функция, создающая сессию БД при каждом запросе к нашему API.
# Срабатывает до запуска остальных функций.
# Всегда закрывает сессию при окончании работы с ней
# @app.middleware("http")
# async def db_session_middleware(request: Request, call_next):
# response = Response("Internal server error", status_code=500)
# try:
# request.state.db = SessionLocal()
# response = await call_next(request)
# finally:
# request.state.db.close()
# return response
@app.get("/api/announcements")#адрес объявлений
def annoncements_list(user_id: int = None, metro: str = None, category: str = None, booked_by: int = -1):
def annoncements_list(user_id: int = None, metro: str = None, category: str = None, booked_by: int = 0):
# Считываем данные из Body и отображаем их на странице.
# В последствии будем вставлять данные в html-форму
@ -136,10 +150,12 @@ def change_book_status(data: schema.Book):
return {"Success": False}
# reginstration
# {"id":1, "email":"poopka@mail.ru", "password":"good", "name":"Vasya", "surname":"Poopkin"}
@app.post("/api/signup")
def create_user(data = Body()):
if database.query(UserDatabase).filter(UserDatabase.email == data["email"]).first() == None:
new_user = UserDatabase(id=data["id"], email=data["email"], password=data["password"], name=data["name"], surname=data["surname"])
new_user = UserDatabase(id=data["id"], email=data["email"], password=data["password"],
hashed_password=get_password_hash(data["password"]), name=data["name"], surname=data["surname"])
database.add(new_user)
database.commit()
database.refresh(new_user) # обновляем состояние объекта
@ -151,7 +167,6 @@ def create_user(data = Body()):
async def login_for_access_token(
form_data: Annotated[OAuth2PasswordRequestForm, Depends()]
):
# разобраться с первым параметром
user = authenticate_user(database, form_data.username, form_data.password)
if not user:
raise HTTPException(
@ -163,19 +178,19 @@ async def login_for_access_token(
access_token = create_access_token(
data={"user_id": user.id}, expires_delta=access_token_expires
)
return access_token
return {"access_token":access_token}
# @app.get("/api/users/me/", response_model=schema.User)
# async def read_users_me(
# current_user: Annotated[User, Depends(get_current_active_user)]
# async def read_users_me( #!!!!!!!!!!!
# current_user: Annotated[schema.User, Depends(get_current_active_user)]
# ):
# return current_user
# return {"data": current_user}
# @app.get("/api/users/me/items/")
# async def read_own_items(
# current_user: Annotated[User, Depends(get_current_active_user)]
# current_user: Annotated[schema.User, Depends(get_current_active_user)]
# ):
# return [{"Current user name": current_user.name, "Current user surname": current_user.surname}]

View File

@ -1,18 +1,25 @@
from sqlalchemy import Column, Integer, String
from sqlalchemy import Column, Integer, String, Boolean
from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase
from fastapi import Depends
from .db import Base
from .db import Base, engine
# class User(SQLAlchemyBaseUserTableUUID, Base):
# name = Column(String, nullable=True)#имя пользователя
class UserDatabase(Base):#класс пользователя
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)#айди пользователя
id = Column(Integer, primary_key=True, index=True, unique=True)#айди пользователя
phone = Column(Integer, nullable=True)#номер телефона пользователя
email = Column(String)#электронная почта пользователя
password = Column(String) # пароль
hashed_password = Column(String)
name = Column(String, nullable=True)#имя пользователя
surname = Column(String)#фамилия пользователя
disabled = Column(Boolean, default=True)
class Announcement(Base): #класс объявления
@ -44,6 +51,12 @@ class Trashbox(Base):#класс мусорных баков
category = Column(String)#категория продукта из объявления
class Poems(Base):#класс поэзии
__tablename__ = "poems"
id = Column(Integer, primary_key=True, index=True) #айди
poem_text = Column(String) # текст стихотворения
# from typing import AsyncGenerator
# from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine
# from fastapi_users.db import SQLAlchemyBaseUserTableUUID, SQLAlchemyUserDatabase

View File

@ -1,3 +1,20 @@
# import uuid
# from fastapi_users import schemas
# class UserRead(schema.BaseUser[uuid.UUID]):
# pass
# class UserCreate(schema.BaseUserCreate):
# pass
# class UserUpdate(schema.BaseUserUpdate):
# pass
from pydantic import BaseModel
from typing import Annotated, Union
@ -7,7 +24,7 @@ class Book(BaseModel):
class Token(BaseModel):
access_token: str
token_type: str
# token_type: str
class TokenData(BaseModel):
@ -19,8 +36,11 @@ class User(BaseModel):
phone: Union[int, None] = None
email: str
name: Union[str, None] = None
surname: Union[str, None] = None
surname: str
disabled: Union[bool, None] = None
class Config:
orm_mode = True
class UserInDB(User):
password: str

2
back/service.py Normal file
View File

@ -0,0 +1,2 @@
from sqlalchemy.orm import Session

View File

@ -1,7 +1,7 @@
from datetime import datetime, timedelta
from typing import Annotated, Union
from fastapi import Depends, FastAPI, HTTPException, status, Response
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
@ -9,30 +9,20 @@ from passlib.context import CryptContext
from sqlalchemy.orm import Session
from sqlalchemy import select
from .db import SessionLocal, database
# from .db import Session, database
from .models import UserDatabase
from .schema import Token, TokenData, UserInDB, User
SECRET_KEY = "09d25e094faa6ca2556c818166b7a9563b93f7099f6f0f4caa6cf63b88e8d3e7"
SECRET_KEY = "SECRET"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# fake_users_db = {
# "johndoe": {
# "email": "johndoe",
# "full_name": "John Doe",
# "email": "johndoe@example.com",
# "hashed_password": "$2b$12$EixZaYVK1fsbw1ZfbX3OXePaWxn96p36WQoeG6Lruj3vjPGga31lW",
# "disabled": False,
# }
# }
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def verify_password(plain_password, hashed_password):
return pwd_context.verify(plain_password, hashed_password)
@ -42,14 +32,14 @@ def get_password_hash(password):
# проблема здесь
def get_user(db: SessionLocal, email: str, response_model=User):
def get_user(db: SessionLocal, email: str):
user_with_required_email = db.query(UserDatabase).filter(UserDatabase.email == email).one()
if user_with_required_email:
return UserInDB(user_with_required_email)
return user_with_required_email
return None
def authenticate_user(db: SessionLocal, email: str, password: str):
def authenticate_user(db: Session, email: str, password: str):
user = get_user(db, email)
if not user:
return False
@ -69,7 +59,7 @@ def create_access_token(data: dict, expires_delta: Union[timedelta, None] = None
return encoded_jwt
async def get_current_user(db: SessionLocal, token: Annotated[str, Depends(oauth2_scheme)], response_model=User):
async def get_current_user(db: SessionLocal, token: Annotated[str, Depends(oauth2_scheme)]):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
@ -84,14 +74,25 @@ async def get_current_user(db: SessionLocal, token: Annotated[str, Depends(oauth
except JWTError:
raise credentials_exception
user = get_user(db, email=token_data.email)
if user == None:
if user is None:
raise credentials_exception
return user
return UserInDB(user)
async def get_current_active_user(
current_user: Annotated[User, Depends(get_current_user)]
current_user: Annotated[UserInDB, Depends(get_current_user)]
):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
return current_user
# def get_db(request: Request):
# return request.state.db
# def get_db():
# db = SessionLocal()
# try:
# yield db
# finally:
# db.close()