Auth works again; relationships between Trashbox and User added

This commit is contained in:
DmitryGantimurov 2023-08-08 01:22:47 +03:00
parent d3d7760c5b
commit 832a2ce985
8 changed files with 185 additions and 43 deletions

View File

@ -77,31 +77,30 @@ def single_annoncement(user_id:int):
# Занести объявление в базу данных # Занести объявление в базу данных
@app.put("/api/announcement")#адрес объявлений @app.put("/api/announcement")#адрес объявлений
def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[datetime.date, Form()], def put_in_db(name: Annotated[str, Form()], category: Annotated[str, Form()], bestBy: Annotated[datetime.date, Form()],
address: Annotated[str, Form()], longtitude: Annotated[float, Form()], latitude: Annotated[float, Form()], address: Annotated[str, Form()], longtitude: Annotated[float, Form()], latitude: Annotated[float, Form()],
description: Annotated[str, Form()], src: UploadFile, metro: Annotated[str, Form()], description: Annotated[str, Form()], metro: Annotated[str, Form()], current_user: Annotated[schemas.User, Depends(utils.get_current_active_user)],
trashId: Annotated[int, Form()] = None): src: Union[UploadFile, None] = None, trashId: Annotated[int, Form()] = None):
# try: try:
userId = 1 # temporary
uploaded_name = "" uploaded_name = ""
if src:
f = src.file
f.seek(0, os.SEEK_END)
if f.tell() > 0:
f.seek(0)
destination = pathlib.Path("./uploads/" + str(hash(f)) + pathlib.Path(src.filename).suffix.lower())
with destination.open('wb') as buffer:
shutil.copyfileobj(f, buffer)
f = src.file uploaded_name = "/uploads/"+destination.name
f.seek(0, os.SEEK_END)
if f.tell() > 0:
f.seek(0)
destination = pathlib.Path("./uploads/" + str(hash(src.file)) + pathlib.Path(src.filename).suffix.lower())
with destination.open('wb') as buffer:
shutil.copyfileobj(src.file, buffer)
uploaded_name = "/uploads/"+destination.name temp_ancmt = models.Announcement(user_id=current_user.id, name=name, category=category, best_by=bestBy,
address=address, longtitude=longtitude, latitude=latitude, description=description, metro=metro, trashId=trashId)
temp_ancmt = models.Announcement(user_id=userId, name=name, category=category, best_by=bestBy, address=address, longtitude=longtitude, latitude=latitude, description=description, src=uploaded_name, metro=metro, trashId=trashId, booked_by=-1)
database.add(temp_ancmt) # добавляем в бд database.add(temp_ancmt) # добавляем в бд
database.commit() # сохраняем изменения database.commit() # сохраняем изменения
database.refresh(temp_ancmt) # обновляем состояние объекта database.refresh(temp_ancmt) # обновляем состояние объекта
return {"Answer" : True} return {"Answer" : True}
# except: except:
# return {"Answer" : False} return {"Answer" : False}
# Удалить объявления из базы # Удалить объявления из базы
@ -130,12 +129,13 @@ def change_book_status(data: schemas.Book):
# reginstration # reginstration
# {"id":1, "email":"poopka@mail.ru", "password":"good", "name":"Vasya", "surname":"Poopkin"}
@app.post("/api/signup") @app.post("/api/signup")
def create_user(data = Body()): def create_user(nickname: Annotated[str, Form()], password: Annotated[str, Form()], name: Annotated[str, Form()]=None,
if database.query(models.User).filter(models.User.email == data["email"]).first() == None: surname: Annotated[str, Form()]=None, avatar: Annotated[UploadFile, Form()]=None):
new_user = models.User(email=data["email"], hashed_password=get_password_hash(data["password"]),
name=data["name"], surname=data["surname"]) if database.query(models.User).filter(models.User.nickname == nickname).first() == None:
new_user = models.User(nickname=nickname, hashed_password=utils.get_password_hash(password),
name=name, surname=surname)
database.add(new_user) database.add(new_user)
database.commit() database.commit()
database.refresh(new_user) # обновляем состояние объекта database.refresh(new_user) # обновляем состояние объекта

View File

@ -4,21 +4,11 @@ from .db import Base, engine
from sqlalchemy.orm import relationship from sqlalchemy.orm import relationship
# импортируем модуль для создания перечислений
import enum
# # класс, необходимый для создания перечисления
# class State(enum.Enum):
# published = 1
# taken = 2
# obsolete = 3
class User(Base):#класс пользователя class User(Base):#класс пользователя
__tablename__ = "users" __tablename__ = "users"
id = Column(Integer, primary_key=True, index=True, unique=True)#айди пользователя id = Column(Integer, primary_key=True, index=True, unique=True)#айди пользователя
email = Column(String)#электронная почта пользователя nickname = Column(String) # никнейм пользователя
hashed_password = Column(String) hashed_password = Column(String)
name = Column(String, nullable=True)#имя пользователя name = Column(String, nullable=True)#имя пользователя
surname = Column(String)#фамилия пользователя surname = Column(String)#фамилия пользователя
@ -28,6 +18,7 @@ class User(Base):#класс пользователя
reg_date = Column(Date) # дата регистрации reg_date = Column(Date) # дата регистрации
announcements = relationship("Announcement", back_populates="user") announcements = relationship("Announcement", back_populates="user")
trashboxes_chosen = relationship("Trashbox", back_populates="user")
class Announcement(Base): #класс объявления class Announcement(Base): #класс объявления
__tablename__ = "announcements" __tablename__ = "announcements"
@ -55,11 +46,15 @@ class Trashbox(Base): #класс мусорных баков
__tablename__ = "trashboxes" __tablename__ = "trashboxes"
id = Column(Integer, primary_key=True, index=True)#айди id = Column(Integer, primary_key=True, index=True)#айди
user_id = Column(Integer, ForeignKey("users.id")) # айди выбравшего мусорку
name = Column(String, nullable=True)#имя пользователя name = Column(String, nullable=True)#имя пользователя
address = Column(String) address = Column(String)
latitude = Column(Integer) latitude = Column(Integer)
longtitude = Column(Integer) longtitude = Column(Integer)
category = Column(String) #категория продукта из объявления category = Column(String) #категория продукта из объявления
date_of_chose = Column(Date) # Дата выбора мусорки пользователем
user = relationship("User", back_populates="trashboxes_chosen")
class Poems(Base):#класс поэзии class Poems(Base):#класс поэзии

View File

@ -2,6 +2,7 @@ from pydantic import BaseModel
from typing import Annotated, Union from typing import Annotated, Union
from datetime import date from datetime import date
from typing import List from typing import List
from fastapi import UploadFile, Form
class Book(BaseModel): class Book(BaseModel):
id: int id: int
@ -21,15 +22,28 @@ class Announcement(BaseModel):
longtitude: float longtitude: float
latitude: float latitude: float
description: str description: str
# src: Union[UploadFile, None] = None #изображение продукта в объявлении
src: Union[str, None] = None #изображение продукта в объявлении src: Union[str, None] = None #изображение продукта в объявлении
metro: str #ближайщее метро от адреса нахождения продукта metro: str #ближайщее метро от адреса нахождения продукта
trashId: Union[int, None] = None trashId: Union[int, None] = None
booked_by: int #статус бронирования (либо -1, либо айди бронирующего) booked_by: Union[int, None] = 0 #статус бронирования (либо 0, либо айди бронирующего)
class Config: class Config:
orm_mode = True orm_mode = True
arbitrary_types_allowed=True arbitrary_types_allowed=True
class PutAnnInDB(BaseModel):
name: Annotated[str, Form()]
category: Annotated[str, Form()]
best_by: Annotated[date, Form()]
address: Annotated[str, Form()]
longtitude: Annotated[float, Form()]
latitude: Annotated[float, Form()]
description: Annotated[str, Form()]
src: Annotated[Union[UploadFile, None], Form()] = None #изображение продукта в объявлении
metro: Annotated[str, Form()] #ближайщее метро от адреса нахождения продукта
class Token(BaseModel): class Token(BaseModel):
access_token: str access_token: str
@ -42,9 +56,9 @@ class TokenData(BaseModel):
class User(BaseModel): class User(BaseModel):
id: int id: int
email: str nickname: str
name: Union[str, None] = None name: Union[str, None] = None
surname: str surname: Union[str, None] = None
disabled: Union[bool, None] = False disabled: Union[bool, None] = False
items: list[Announcement] = [] items: list[Announcement] = []

View File

@ -17,7 +17,7 @@ SECRET_KEY = "SECRET"
ALGORITHM = "HS256" ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30 ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/token")
def get_db(): def get_db():
@ -36,15 +36,22 @@ def get_password_hash(password):
return pwd_context.hash(password) return pwd_context.hash(password)
def get_user(db: Annotated[Session, Depends(get_db)], user_id: int): def get_user_by_nickname(db: Annotated[Session, Depends(get_db)], nickname: str):
user_with_required_id = db.query(models.User).filter(models.User.nickname == nickname).first()
if user_with_required_id:
return user_with_required_id
return None
def get_user_by_id(db: Annotated[Session, Depends(get_db)], user_id: int):
user_with_required_id = db.query(models.User).filter(models.User.id == user_id).first() user_with_required_id = db.query(models.User).filter(models.User.id == user_id).first()
if user_with_required_id: if user_with_required_id:
return user_with_required_id return user_with_required_id
return None return None
def authenticate_user(db: Annotated[Session, Depends(get_db)], email: str, password: str): def authenticate_user(db: Annotated[Session, Depends(get_db)], nickname: str, password: str):
user = get_user(user_id = user_id) user = get_user_by_nickname(db=db, nickname=nickname)
if not user: if not user:
return False return False
if not verify_password(password, user.hashed_password): if not verify_password(password, user.hashed_password):
@ -77,10 +84,10 @@ async def get_current_user(db: Annotated[Session, Depends(get_db)], token: Annot
token_data = schemas.TokenData(user_id=user_id) token_data = schemas.TokenData(user_id=user_id)
except JWTError: except JWTError:
raise credentials_exception raise credentials_exception
user = get_user(db, user_id=token_data.user_id) user = get_user_by_id(db, user_id=token_data.user_id)
if user is None: if user is None:
raise credentials_exception raise credentials_exception
return schemas.User(id=user.id, email=user.email, name=user.name, surname=user.surname, disabled=user.disabled, items=user.items) return schemas.User(id=user.id, nickname=user.nickname, name=user.name, surname=user.surname, disabled=user.disabled, items=user.announcements)
async def get_current_active_user( async def get_current_active_user(

View File

@ -0,0 +1,34 @@
"""email->nickname in User model
Revision ID: 58290a82b821
Revises: 9c19b9658512
Create Date: 2023-08-07 23:37:58.017279
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '58290a82b821'
down_revision = '9c19b9658512'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.add_column(sa.Column('nickname', sa.String(), nullable=True))
batch_op.drop_column('email')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.add_column(sa.Column('email', sa.VARCHAR(), nullable=True))
batch_op.drop_column('nickname')
# ### end Alembic commands ###

View File

@ -0,0 +1,28 @@
"""created relationships between Trashbox and User
Revision ID: 96470e6327e0
Revises: b806af0cc2cb
Create Date: 2023-08-08 00:06:18.745504
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '96470e6327e0'
down_revision = 'b806af0cc2cb'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###

View File

@ -0,0 +1,28 @@
"""created relationships between Trashbox and User
Revision ID: b806af0cc2cb
Revises: 58290a82b821
Create Date: 2023-08-08 00:05:55.175838
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b806af0cc2cb'
down_revision = '58290a82b821'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
pass
# ### end Alembic commands ###

View File

@ -0,0 +1,36 @@
"""created relationships between Trashbox and User; (foreign key added to Trashbox table)
Revision ID: ee035dd94fbb
Revises: 96470e6327e0
Create Date: 2023-08-08 00:11:35.443724
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'ee035dd94fbb'
down_revision = '96470e6327e0'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('trashboxes', schema=None) as batch_op:
batch_op.add_column(sa.Column('user_id', sa.Integer(), nullable=True))
batch_op.add_column(sa.Column('date_of_chose', sa.Date(), nullable=True))
# batch_op.create_foreign_key(None, 'users', ['user_id'], ['id'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
with op.batch_alter_table('trashboxes', schema=None) as batch_op:
# batch_op.drop_constraint(None, type_='foreignkey')
batch_op.drop_column('date_of_chose')
batch_op.drop_column('user_id')
# ### end Alembic commands ###