Compare commits

..

No commits in common. "main" and "another" have entirely different histories.

10 changed files with 118 additions and 685 deletions

View file

@ -1,259 +1,27 @@
from enum import Enum from sqlalchemy import Column, Integer, String, Enum, DateTime
import random import enum, datetime
import smtplib
from backend.config import SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES ,pwd_context, get_session_db, Base, user_collection
from datetime import datetime, timedelta, timezone
from pydantic import BaseModel
from fastapi import Depends, HTTPException
from typing import Annotated
from fastapi.security import OAuth2PasswordBearer
from pydantic.networks import EmailStr
from sqlalchemy import Integer, DateTime, ForeignKey
from sqlalchemy.orm import Session, relationship, mapped_column, Mapped
from sqlalchemy.dialects.postgresql import ARRAY
from email.message import EmailMessage
from typing import TYPE_CHECKING
from ..config import Base
if TYPE_CHECKING: class Role(str, enum.Enum):
from ..collectionObj.models import CollectionsDB #iç içe import döngüsünü önlemek için TYPE_CHECKING kullanıyoruz
import jwt
class Token(BaseModel):
access_token: str
token_type: str
### ENUMS ###
class Role(str, Enum):
user = "user"
admin = "admin" admin = "admin"
guest = "guest" user = "user"
mod = "mod" mod = "mod"
class Status(str, Enum): class Status(str, enum.Enum):
active = "active"
banned = "banned" banned = "banned"
active = "active"
suspended = "suspended" suspended = "suspended"
### KULLANICI MODELLERİ ### sqlalchemy ve pydantic modelleri farklıdır class User(Base):
class UserBase(BaseModel): #bu bir veri tabanı modeli değil !!!! lütfen dikkat et __tablename__ = "users"
username: str | None = None #Option yerine Union kullanabilirsin user_id = Column(Integer, primary_key=True)
role: Role | None = None username = Column(String, unique=True)
status: Status | None = None name = Column(String)
surname = Column(String)
class UserInDb(UserBase): hashedPassword = Column(String)
user_id: int | None = None email = Column(String, unique=True)
email: EmailStr | None = None role = Column(Enum(Role), default=Role.user)
hashed_password: str | None = None status = Column(Enum(Status), default=Status.active)
bio = Column(String(144))
class UserPublic(BaseModel): created_date = Column(DateTime, default=datetime.datetime.utcnow)
username : str | None = None
role : Role | None = None
status : Status | None = None
class UserCreate(BaseModel):
username: str | None = None
role: Role | None = None
email : EmailStr | None = None
status: Status | None = None
password : str | None = None
### VERİTABANI MODELİ ###
class DBUser(Base):
__tablename__ = "users_table"
user_id: Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
#collection_id : Mapped[list[int]] = mapped_column(Integer, ForeignKey("collections_table.collection_id"), nullable=True) # collection_id ile ilişki
username : Mapped[str] = mapped_column(unique=True, index=True, nullable=False)
email : Mapped[str] = mapped_column(unique=True, index=True, nullable=False)
hashed_password : Mapped[str] = mapped_column(nullable=False)
role : Mapped[Role] = mapped_column(default=Role.user)
status : Mapped[Status] = mapped_column(default=Status.active)
created_date : Mapped[datetime] = mapped_column(DateTime, default=datetime.now()) #datetime.datetime -> python, DateTime -> sqlalchemy
bio : Mapped[str] = mapped_column(default="No bio")
follow_users : Mapped[list[int]] = mapped_column(ARRAY(Integer), default=[]) # takip edilen kullanıcılar
# -> buralar diğer tablolar ile olan ilişkiler
#items : Mapped[list['Items']] = relationship("Items", back_populates="user", cascade="all, delete-orphan") items'e direk değil collection üzerinden erişiyoruz
collections : Mapped[list['CollectionsDB']] = relationship(
"CollectionsDB",
secondary=user_collection,
back_populates="users",
lazy='select'
) # collection'lar ile olan ilişki
### AUTH ###
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
### SERVİSLER ###
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
def authenticate_user(
session: Annotated[Session, Depends(get_session_db)],
username: str,
password: str
) -> UserInDb | None:
user = session.query(DBUser).filter(DBUser.username == username).first()
if user is None or not verify_password(password, user.hashed_password): #sqlalchemy'de bu şekilde kontrol ediliyor None ile
return None
return user
def create_access_token(
data: dict,
expires_delta: Annotated[timedelta, None] = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES),
) -> str:
to_encode = data.copy()
expire = datetime.now(timezone.utc) + expires_delta
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def get_user(
session: Annotated[Session, Depends(get_session_db)],
username: str
) -> UserInDb | None:
user = session.query(DBUser).filter(DBUser.username == username).first()
return user
async def get_current_user(
token: Annotated[str, Depends(oauth2_scheme)],
session: Annotated[Session, Depends(get_session_db)]
) -> UserPublic:
credentials_exception = HTTPException(
status_code=401,
detail="Invalid credentials currently",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username : str | None = payload.get("sub")
user = UserInDb.model_validate(payload)
if username is None:
raise credentials_exception
except jwt.PyJWTError:
raise credentials_exception
user = await get_user(session, username)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(
current_user: Annotated[UserInDb, Depends(get_current_user)]
) -> UserPublic:
if current_user.status == Status.banned:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
### Kullanıcı kaydı
def register_user(
session: Annotated[Session, Depends(get_session_db)],
user: Annotated[UserCreate, Depends()]
) -> UserPublic:
user_dict = user.dict() # kullanıcıdan gelen verileri alıyoruz çunku şifreyi hashleyeceğiz
user_dict['hashed_password'] = get_password_hash(user.password) # şifreyi hashliyoruz
if not verify_password(user.password, user_dict['hashed_password']):
raise HTTPException(status_code=400, detail="Password hashing failed") # şifre hashleme işlemi başarısız oldu
# Kullanıcı adı ve e-posta adresinin benzersiz olduğunu kontrol et
existing_user = session.query(DBUser).filter(
(DBUser.username == user.username) | (DBUser.email == user.email)
).first()
if existing_user:
raise HTTPException(status_code=400, detail="Username or email already registered")
user_dict['created_date'] = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S") # kullanıcı oluşturulma tarihi
user_dict.pop('password') ##password'u veri tabanına eklemiyoruz zaten sınıfımızda tanımlı değil hata verir
db_user = DBUser(**user_dict) #alchemy ile pydantic modelleri farklıdır bir birine
session.add(db_user) # donuşum yaparken dikkat et
session.commit()
session.refresh(db_user)
return db_user
def find_user_w_email(
session: Annotated[Session, Depends(get_session_db)],
email: EmailStr | None = None,
):
exist_user = session.query(DBUser).filter(DBUser.email == email).first() #email ile kullanıcıyı bul
if exist_user is None:
raise HTTPException(status_code=400, detail="User not found")
if exist_user.status == Status.banned:
raise HTTPException(status_code=400, detail="Inactive user")
return True
def send_password_to_email(
session: Annotated[Session, Depends(get_session_db)],
email: EmailStr | None = None,
) -> str:
msg = EmailMessage() #obje oluştur
msg['Subject'] = 'Password Reset'
msg['From'] = 'hansneiumann@gmail.com'
msg['To'] = email
veritification_code = generate_password_reset_number()
msg.set_content(veritification_code)
with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
smtp.login("hansneiumann@gmail.com", "rwaq mbil lzut dgja")
smtp.send_message(msg)
update_password_w_email(session, email=email, password=veritification_code) #şifreyi güncelle
def generate_password_reset_number() -> str:
return str(random.randint(10000000, 99999999)) # 8 haneli rastgele bir sayı döndür
def update_password_w_email(
session: Annotated[Session, Depends(get_session_db)],
password: str | None = None,
email: EmailStr | None = None,
) -> dict:
hashed_password = get_password_hash(password)
session.query(DBUser).filter(DBUser.email == email).update({"hashed_password": hashed_password})
session.commit()
return {"message": "Password updated successfully"}
def update_password_w_user(
session: Annotated[Session, Depends(get_session_db)],
user: Annotated[DBUser , None],
password: str | None = None,
) -> any:
hashed_password = get_password_hash(password)
session.query(DBUser).filter(DBUser.user_id == user.user_id).update({"hashed_password": hashed_password})
session.commit()

View file

@ -1,12 +1,14 @@
from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks import os
from .models import Token, UserPublic, authenticate_user, create_access_token, UserCreate, find_user_w_email, get_current_user, register_user, send_password_to_email, update_password_w_user
from datetime import timedelta
from typing import Annotated
from ..config import get_session_db
from fastapi.security import OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from pydantic.networks import EmailStr
from fastapi import APIRouter, HTTPException
import bcrypt
import jwt
from fastapi import Depends
from sqlalchemy.orm import Session
from .models import User
from .schemas import UserCreate, UserOut, UserLogin
from ..config import get_db
router = APIRouter( router = APIRouter(
prefix="/auth", prefix="/auth",
@ -15,61 +17,40 @@ router = APIRouter(
dependencies=[], dependencies=[],
) )
@router.post('/login') def create_token(user: User):
async def login_for_access_token( return jwt.encode({"sub": user.username}, os.getenv("SECRET_KEY"), algorithm=os.getenv("ALGORITHM"))
form_data : Annotated[OAuth2PasswordRequestForm, Depends()],
session : Annotated[Session, Depends(get_session_db)],
) -> Token:
user = authenticate_user(session, form_data.username, form_data.password) def verify_token(token: str):
if not user: try:
raise HTTPException( data = jwt.decode(token, os.getenv("SECRET_KEY"), algorithms=[os.getenv("ALGORITHM")])
status_code=status.HTTP_401_UNAUTHORIZED, return data.get("sub")
detail="Incorrect username or password", except jwt.ExpiredSignatureError:
headers={"WWW-Authenticate": "Bearer"}, raise HTTPException(401, "Token expired")
) except jwt.InvalidTokenError:
access_token_expires = timedelta(minutes=30) raise HTTPException(401, "Invalid token")
access_token = create_access_token(
data={"sub": user.username, "role": user.role, 'status': user.status}, expires_delta=access_token_expires
)
return Token(access_token=access_token, token_type="bearer")
@router.post('/register', response_model=UserPublic) #userPublic güvenli bir model @router.post("/register")
async def create_user( def register(user: UserCreate, db: Session = Depends(get_db)):
session : Annotated[Session, Depends(get_session_db)], if db.query(User).filter_by(username=user.username).first():
user : Annotated[UserCreate, Depends()] raise HTTPException(400, "Username taken")
): hashed = bcrypt.hashpw(user.password.encode(), bcrypt.gensalt()).decode()
db_user = User(**user.model_dump(exclude={"password"}), hashedPassword=hashed)
return register_user(session, user) db.add(db_user)
db.commit()
@router.post('/password_reset') return {"msg": "User created"}
async def password_reset(
session : Annotated[Session, Depends(get_session_db)],
email : Annotated[EmailStr, None] = None,
task: Annotated[BackgroundTasks, None] = None, # BackgroundTasks, task'ı arka planda çalıştırmak için kullanıyoruz
):
if not find_user_w_email(session, email):
return HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="bad request",
)
task.add_task(send_password_to_email, session, email)
return {"message": "New password has been sent to your email."}
@router.post('/update_password')
async def update_password(
user: Annotated[str, Depends(get_current_user)],
session: Annotated[Session, Depends(get_session_db)],
new_password: Annotated[str, None] = None,
) -> dict:
update_password_w_user(session, user, new_password)
return {"message": "Password updated successfully."}
@router.post("/login")
def login(user: UserLogin, db: Session = Depends(get_db)):
db_user = db.query(User).filter_by(username=user.username).first()
if not db_user or not bcrypt.checkpw(user.password.encode(), db_user.hashedPassword.encode()):
raise HTTPException(401, "Invalid creds")
return {"token": create_token(db_user)}
@router.get("/me", response_model=UserOut)
def get_me(token: str, db: Session = Depends(get_db)):
username = verify_token(token)
if not username:
raise HTTPException(401, "Invalid token")
user = db.query(User).filter_by(username=username).first()
return user

23
auth/schemas.py Normal file
View file

@ -0,0 +1,23 @@
from pydantic import BaseModel, EmailStr
from .models import Role, Status
class UserCreate(BaseModel):
username: str
name: str
surname: str
password: str
email: EmailStr
bio: str = ""
class UserOut(BaseModel):
username: str
name: str
surname: str
email: EmailStr
role: Role
status: Status
bio: str
class UserLogin(BaseModel):
username: str
password: str

View file

@ -1,173 +0,0 @@
from fastapi import HTTPException, Depends
from sqlalchemy import Integer, String, Boolean
from pydantic import BaseModel
from sqlalchemy.orm import Session, relationship, mapped_column, Mapped
from ..config import Base, get_session_db, user_collection, collection_item
from ..auth.models import DBUser
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from ..items.models import Items, Item
###### SCHEMAS #########
class CollectionBase(BaseModel):
collection_name : str | None = None
collection_description : str | None = None
visibility : bool | None = None
class CollectionCreate(CollectionBase):
pass
class CollectionPublic(CollectionBase):
collection_id : int | None = None
class Config:
from_attributes = True #sqlalchemy ile pydantic arasında geçiş yapabilmek için kullanılır
class CollectionUpdate(CollectionBase):
pass
##### veri tabanı modelleri #####
class CollectionsDB(Base):
__tablename__ = "collections_table"
collection_id : Mapped[int] = mapped_column(Integer, primary_key=True, index=True, autoincrement=True)
#user_id : Mapped[int] = mapped_column(Integer, ForeignKey("users_table.user_id"), nullable=False) # user_id ile ilişki
#item_id : Mapped[list[int]] = mapped_column(Integer, ForeignKey("items_table.item_id"), nullable=False) # item_id ile ilişki
visibility : Mapped[bool] = mapped_column(Boolean, default=True)
collection_name : Mapped[str] = mapped_column(String, nullable=False)
collection_description : Mapped[str] = mapped_column(String, default="No description")
# ilişkiler
users : Mapped[list['DBUser']] = relationship(
"DBUser",
secondary=user_collection,
back_populates="collections",
lazy='select'
) #back_populates karşı tarafın ismi
items : Mapped[list['Items']] = relationship(
"Items",
secondary=collection_item,
back_populates="collections" ,
lazy='select'
)
#### collection bir item listesi birde kullanıcı listesi tutacak
def create_colletion(
collection: CollectionCreate | None = None,
user_id : int | None = None
) -> bool:
"""
Collection oluşturma fonksiyonu
"""
if collection is None:
raise HTTPException(status_code=400, detail="Collection is None returned")
session = next(get_session_db()) # -> get_session_db() fonksiyonu daima generator döndürür next ile çağırmalısın
user = session.query(DBUser).filter(DBUser.user_id == user_id).first()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
try:
new_collection = CollectionsDB(
collection_name=collection.collection_name,
collection_description=collection.collection_description,
visibility=collection.visibility
)
new_collection.users.append(user)
session.add(new_collection)
session.commit()
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error creating collection: {e}")
return True
def get_collections(
user_id : int | None = None
) -> list[CollectionPublic] | None:
"""
Kullanıcının collectionlarını döndürür
"""
if user_id is None:
raise HTTPException(status_code=400, detail="User id is None")
session = next(get_session_db()) # -> get_session_db() fonksiyonu daima generator döndürür next ile çağırmalısın
collections = session.query(CollectionsDB).filter(CollectionsDB.users.any(user_id=user_id)).all()
if collections is None:
raise HTTPException(status_code=404, detail="No collections found")
return collections
def update_collection(
collection: CollectionUpdate | None = None,
user_id : int | None = None,
collection_id : int | None = None
) -> bool:
"""
Collection güncelleme fonksiyonu
"""
if collection is None:
raise HTTPException(status_code=400, detail="Collection is None returned")
session = next(get_session_db()) # -> get_session_db() fonksiyonu daima generator döndürür next ile çağırmalısın
user = session.query(DBUser).filter(DBUser.user_id == user_id).first()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
collection_to_update = session.query(CollectionsDB).filter(CollectionsDB.collection_id == collection_id).first()
if collection_to_update is None:
raise HTTPException(status_code=404, detail="Collection not found")
try:
collection_to_update.collection_name = collection.collection_name
collection_to_update.collection_description = collection.collection_description
collection_to_update.visibility = collection.visibility
session.commit()
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error updating collection: {e}")
return True
def delete_collection(
user_id : int | None = None,
collection_id : int | None = None
) -> bool:
"""
Collection silme fonksiyonu
"""
if user_id is None or collection_id is None:
raise HTTPException(status_code=400, detail="User id or collection id is None")
session = next(get_session_db()) # -> get_session_db() fonksiyonu daima generator döndürür next ile çağırmalısın
user = session.query(DBUser).filter(DBUser.user_id == user_id).first()
if user is None:
raise HTTPException(status_code=404, detail="User not found")
collection_to_delete = session.query(CollectionsDB).filter(CollectionsDB.collection_id == collection_id).first()
if collection_to_delete is None:
raise HTTPException(status_code=404, detail="Collection not found")
try:
session.delete(collection_to_delete)
session.commit()
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error deleting collection: {e}")
return True

View file

@ -1,60 +0,0 @@
from fastapi import FastAPI, APIRouter
from .models import CollectionPublic, CollectionCreate, CollectionUpdate
from .models import get_collections, create_colletion, update_collection, delete_collection
router = APIRouter(
prefix="/collections",
tags=["collections"],
responses={404: {"description": "Not found"}},
dependencies=[],
)
@router.get("/{user_id}")
async def get_collections_api(user_id: int) -> list[CollectionPublic]:
"""
Kullanıcının collectionlarını döndürür
"""
_collections : list[CollectionPublic] = get_collections(user_id=user_id)
return _collections
@router.post("/{user_id}")
async def create_collection(
user_id: int,
collection: CollectionCreate
) -> bool:
"""
Collection oluşturma fonksiyonu
"""
_result = create_colletion(user_id=user_id, collection=collection)
return _result
@router.put("/{user_id}/{collection_id}")
async def update_collection_api(
user_id: int,
collection_id : int,
collection: CollectionUpdate
) -> bool:
"""
Collection güncelleme fonksiyonu
"""
_result = update_collection(user_id=user_id, collection_id=collection_id, collection=collection)
return _result
@router.delete("/{user_id}/{collection_id}")
async def delete_collection_api(
user_id: int,
collection_id : int
) -> bool:
"""
Collection silme fonksiyonu
"""
_result = delete_collection(user_id=user_id, collection_id=collection_id)
return _result

View file

@ -1,64 +1,39 @@
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, DeclarativeBase from sqlalchemy.orm import sessionmaker, declarative_base
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy import Table, Column, Integer, String, Float, Boolean, ForeignKey
from passlib.context import CryptContext
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
load_dotenv() load_dotenv()
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") DATABASE_URL = (
f"postgresql://{os.getenv('USERNAME_DB')}:"
SECRET_KEY = os.getenv("SECRET_KEY") f"{os.getenv('PASSWORD_DB')}@"
ALGORITHM = os.getenv("ALGORITHM") f"{os.getenv('HOST_DB')}:"
ACCESS_TOKEN_EXPIRE_MINUTES = int(os.getenv("ACCESS_TOKEN_EXPIRE_MINUTES", 30)) f"{os.getenv('PORT_DB')}/"
f"{os.getenv('NAME_DB')}"
DATABASE_URL = os.getenv("DATABASE_URL") )
# Engine oluştur
engine = create_engine(DATABASE_URL, echo=False)
# Session factory oluştur
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
#Base = declarative_base() #sqlalchemy için bu sınıfı kullanıyoruz 'class DBUser(Base)' şeklinde tanımlıyoruz
class Base(DeclarativeBase):
pass #yeni sqlalchemy sürümünde bu sınıfı kullanıyoruz
#models te içe aktarmayı unutma engine = create_engine(DATABASE_URL)
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()
def init_db(): from .auth.models import *
#Base.metadata.drop_all(engine) # Veritabanını her başlangıcta siler burayada dikkat !!!!!!!! from .items.models import *
Base.metadata.create_all(bind=engine) # Veritabanını oluşturur
# Session dependency (FastAPI için) Base.metadata.create_all(bind=engine)
def get_session_db() -> 'Generator[Session, None]':
def get_db():
db = SessionLocal() db = SessionLocal()
try: try:
yield db yield db
finally: finally:
db.close() db.close()
user_collection = Table( # user -> collection
"user_collection",
Base.metadata,
Column("user_id", Integer, ForeignKey("users_table.user_id"), primary_key=True),
Column("collection_id", Integer, ForeignKey("collections_table.collection_id"), primary_key=True),
)
collection_item = Table( # collection -> item
"collection_item",
Base.metadata,
Column("collection_id", ForeignKey("collections_table.collection_id"), primary_key=True),
Column("item_id", ForeignKey("items_table.item_id"), primary_key=True)
)
### SECRET KEY ###
origins = [ origins = [
"http://localhost", "http://localhost",
"http://localhost:8080", "http://localhost:8080",
@ -67,10 +42,6 @@ origins = [
] ]
app = FastAPI() app = FastAPI()
@app.on_event("startup")
def startup_event():
init_db()
app.add_middleware( app.add_middleware(
CORSMiddleware, CORSMiddleware,
allow_origins=origins, allow_origins=origins,
@ -78,6 +49,3 @@ app.add_middleware(
allow_methods=["*"], allow_methods=["*"],
allow_headers=["*"], allow_headers=["*"],
) )

View file

@ -1,78 +1,15 @@
from datetime import datetime, timedelta, timezone from datetime import datetime
from typing import Annotated from ..config import Base
from sqlalchemy import DateTime from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
from pydantic import BaseModel from sqlalchemy.orm import relationship, Mapped, mapped_column
from fastapi import Depends
from sqlalchemy.orm import Session, relationship, mapped_column, Mapped
from sqlalchemy import String, Float, Integer, ForeignKey
from sqlalchemy.dialects.postgresql import ARRAY
from ..config import Base, get_session_db, collection_item
from typing import TYPE_CHECKING
from ..auth.models import Role, Status, UserBase
from ..collectionObj.models import CollectionsDB
class Item(Base):
class UserProfileBase(UserBase): __tablename__ = "items"
bio : str | None = None item_id = Column(Integer, primary_key=True)
created_date : datetime | None = None name = Column(String(100), nullable=False)
# collection : list[str] | None = None description = Column(String(500), nullable=True)
price = Column(Integer, nullable=False)
class UserProfileID(UserProfileBase): created_date = Column(DateTime, default=datetime.utcnow)
user_id : int | None = None updated_date = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
user: Mapped["User"] = relationship(back_populates="items")
class UserProfilePublic(UserProfileBase):
pass
class UserProfilePrivate(UserProfilePublic):
#collection : list[str] | None = None
role : Role | None = None
status : Status | None = None
follow_user : list[int] | None = None
items : list['Item'] | None = None
######## ITEMS ######
class BaseItem(BaseModel):
item_created_date : datetime | None = None
item_location : str | None = None
item_type : str | None = None
item_content : str | None = None
class ItemCreate(BaseItem): # item oluşturma için ekstra bir ihtiyaci olmaz
pass
class Item(BaseItem):
item_id : int | None = None
user_id : int | None = None
item_score : float | None = None
class Config:
from_attributes = True #sqlalchemy ile pydantic arasında geçiş yapabilmek için kullanılır
##### VERİTABANI MODELİ #####
# Tüm modeller AUTH'da veri tabanına işlendi yukardaki
#modeller veri tabanında mevcuttur. Değiştirmek için AUTH'daki
# DBUser modelini değiştirip tekrar veri tabanına işleyebilirsin
class Items(Base):
__tablename__ = "items_table"
item_id : Mapped[int] = mapped_column(primary_key=True, index=True, autoincrement=True)
#collection_id : Mapped[list[int]] = mapped_column(Integer, ForeignKey("collections_table.collection_id"), nullable=True) # collection_id ile ilişki
item_created_date : Mapped[datetime] = mapped_column(DateTime, default=datetime.now())
item_location: Mapped[str] = mapped_column(String, default="No location")
item_type: Mapped[str] = mapped_column(String, default="No type")
item_content: Mapped[str] = mapped_column(String, default="No content")
item_score: Mapped[float] = mapped_column(Float, default=0.0)
# ilişkiler
collections : Mapped[list['CollectionsDB']]= relationship(
"CollectionsDB",
secondary=collection_item,
back_populates="items",
lazy='select'
) #back_populates karşı tarafın ismi

View file

@ -1,9 +1,4 @@
from .models import ItemCreate, UserProfileBase, UserProfileID, UserProfilePrivate, UserProfilePublic
from fastapi import APIRouter, Depends from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from ..config import get_session_db
from typing import Annotated
from ..auth.models import get_current_active_user
router = APIRouter( router = APIRouter(
prefix="/items", prefix="/items",
@ -12,8 +7,7 @@ router = APIRouter(
dependencies=[], dependencies=[],
) )
#tüm crud işlemleri yeni veri tabanı modeli ile yapılacak
@router.get("/")
async def get_items():
return {"message": "List of items"}

View file

@ -1,8 +1,6 @@
from .config import app from .config import app
from .auth.router import router as auth_router from .auth.router import router as auth_router
from .items.router import router as items_router from .items.router import router as items_router
from .collectionObj.router import router as collections_router
app.include_router(auth_router) app.include_router(auth_router)
app.include_router(collections_router)
app.include_router(items_router) app.include_router(items_router)

View file

@ -1,6 +1,5 @@
annotated-types==0.7.0 annotated-types==0.7.0
anyio==4.9.0 anyio==4.9.0
bcrypt==4.3.0
certifi==2025.4.26 certifi==2025.4.26
click==8.1.8 click==8.1.8
dnspython==2.7.0 dnspython==2.7.0
@ -40,5 +39,3 @@ uvicorn==0.34.2
uvloop==0.21.0 uvloop==0.21.0
watchfiles==1.0.5 watchfiles==1.0.5
websockets==15.0.1 websockets==15.0.1
passlib[bcrypt]==1.7.4