api ready

parent 7cd2edc7
__pycache__/
.env/
from sqlalchemy import create_engine, ForeignKey, Date, Enum as SQLEnum
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import Column, Integer, String, SmallInteger
from enum import Enum
# Database configuration
SQLALCHEMY_DATABASE_URL = "mysql+pymysql://webapp:Ej]mMiSZCr7)BzAp@localhost/webapp"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
# Enum for loan status
class LoanStatus(str, Enum):
reserved = "reserved"
started = "started"
ended = "ended"
# SQLAlchemy Models
class UserDB(Base):
__tablename__ = "user"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
email = Column(String(50), unique=True, nullable=False)
password = Column(String(256), nullable=False)
role = Column(SmallInteger, nullable=False, default=0)
# Relationships
books = relationship("BookDB", back_populates="owner_rel")
loans = relationship("LoanDB", back_populates="user")
class BookDB(Base):
__tablename__ = "book"
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
owner = Column(Integer, ForeignKey('user.id'), nullable=False)
title = Column(String(80), nullable=False)
author = Column(String(80), nullable=True)
# Relationships
owner_rel = relationship("UserDB", back_populates="books")
loans = relationship("LoanDB", back_populates="book")
class LoanDB(Base):
__tablename__ = "loan"
id_user = Column(Integer, ForeignKey('user.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
id_book = Column(Integer, ForeignKey('book.id', ondelete='CASCADE', onupdate='CASCADE'), primary_key=True)
status = Column(SQLEnum(LoanStatus), nullable=False, default=LoanStatus.reserved)
start = Column(Date, primary_key=True, nullable=True)
end = Column(Date, nullable=True)
# Relationships
user = relationship("UserDB", back_populates="loans")
book = relationship("BookDB", back_populates="loans")
# Database Dependency
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
\ No newline at end of file
from typing import List
from datetime import date
from fastapi import FastAPI, HTTPException, Depends
from passlib.context import CryptContext
from sqlalchemy.orm import Session
from typing import Optional
from pydantic import BaseModel, EmailStr
from datetime import date
from database import *
# Pydantic Models
class UserBase(BaseModel):
email: EmailStr
role: int = 0
class UserCreate(UserBase):
password: str
class User(UserBase):
id: int
class Config:
from_attributes = True
class BookBase(BaseModel):
title: str
author: Optional[str] = None
owner: int
class BookCreate(BookBase):
pass
class Book(BookBase):
id: int
class Config:
from_attributes = True
class LoanBase(BaseModel):
id_user: int
id_book: int
status: LoanStatus = LoanStatus.reserved
start: Optional[date] = None
end: Optional[date] = None
class LoanCreate(LoanBase):
pass
class Loan(LoanBase):
class Config:
from_attributes = True
# Password hashing
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
app = FastAPI()
# User CRUD Operations
@app.post("/users/", response_model=User)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
db_user = db.query(UserDB).filter(UserDB.email == user.email).first()
if db_user:
raise HTTPException(status_code=400, detail="Email already registered")
hashed_password = pwd_context.hash(user.password)
db_user = UserDB(
email=user.email,
password=hashed_password,
role=user.role
)
try:
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.get("/users/", response_model=List[User])
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
users = db.query(UserDB).offset(skip).limit(limit).all()
return users
@app.get("/users/{user_id}", response_model=User)
def read_user(user_id: int, db: Session = Depends(get_db)):
db_user = db.query(UserDB).filter(UserDB.id == user_id).first()
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user
@app.put("/users/{user_id}", response_model=User)
def update_user(user_id: int, user: UserCreate, db: Session = Depends(get_db)):
db_user = db.query(UserDB).filter(UserDB.id == user_id).first()
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
# Update email if it's changed and not already taken
if user.email != db_user.email:
existing_user = db.query(UserDB).filter(UserDB.email == user.email).first()
if existing_user:
raise HTTPException(status_code=400, detail="Email already registered")
db_user.email = user.email
# Update password
db_user.password = pwd_context.hash(user.password)
db_user.role = user.role
try:
db.commit()
db.refresh(db_user)
return db_user
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.delete("/users/{user_id}")
def delete_user(user_id: int, db: Session = Depends(get_db)):
db_user = db.query(UserDB).filter(UserDB.id == user_id).first()
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
try:
db.delete(db_user)
db.commit()
return {"message": "User deleted successfully"}
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
# Book CRUD Operations
@app.post("/books/", response_model=Book)
def create_book(book: BookCreate, db: Session = Depends(get_db)):
db_book = BookDB(**book.dict())
try:
db.add(db_book)
db.commit()
db.refresh(db_book)
return db_book
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.get("/books/", response_model=List[Book])
def read_books(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
books = db.query(BookDB).offset(skip).limit(limit).all()
return books
@app.get("/books/{book_id}", response_model=Book)
def read_book(book_id: int, db: Session = Depends(get_db)):
db_book = db.query(BookDB).filter(BookDB.id == book_id).first()
if db_book is None:
raise HTTPException(status_code=404, detail="Book not found")
return db_book
@app.put("/books/{book_id}", response_model=Book)
def update_book(book_id: int, book: BookCreate, db: Session = Depends(get_db)):
db_book = db.query(BookDB).filter(BookDB.id == book_id).first()
if db_book is None:
raise HTTPException(status_code=404, detail="Book not found")
for key, value in book.dict().items():
setattr(db_book, key, value)
try:
db.commit()
db.refresh(db_book)
return db_book
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.delete("/books/{book_id}")
def delete_book(book_id: int, db: Session = Depends(get_db)):
db_book = db.query(BookDB).filter(BookDB.id == book_id).first()
if db_book is None:
raise HTTPException(status_code=404, detail="Book not found")
try:
db.delete(db_book)
db.commit()
return {"message": "Book deleted successfully"}
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
# Loan CRUD Operations
@app.post("/loans/", response_model=Loan)
def create_loan(loan: LoanCreate, db: Session = Depends(get_db)):
db_loan = LoanDB(**loan.dict())
try:
db.add(db_loan)
db.commit()
db.refresh(db_loan)
return db_loan
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.get("/loans/", response_model=List[Loan])
def read_loans(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
loans = db.query(LoanDB).offset(skip).limit(limit).all()
return loans
@app.get("/loans/{user_id}/{book_id}/{start_date}", response_model=Loan)
def read_loan(user_id: int, book_id: int, start_date: date, db: Session = Depends(get_db)):
db_loan = db.query(LoanDB).filter(
LoanDB.id_user == user_id,
LoanDB.id_book == book_id,
LoanDB.start == start_date
).first()
if db_loan is None:
raise HTTPException(status_code=404, detail="Loan not found")
return db_loan
@app.put("/loans/{user_id}/{book_id}/{start_date}", response_model=Loan)
def update_loan(
user_id: int,
book_id: int,
start_date: date,
loan: LoanCreate,
db: Session = Depends(get_db)
):
db_loan = db.query(LoanDB).filter(
LoanDB.id_user == user_id,
LoanDB.id_book == book_id,
LoanDB.start == start_date
).first()
if db_loan is None:
raise HTTPException(status_code=404, detail="Loan not found")
for key, value in loan.dict().items():
setattr(db_loan, key, value)
try:
db.commit()
db.refresh(db_loan)
return db_loan
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
@app.delete("/loans/{user_id}/{book_id}/{start_date}")
def delete_loan(user_id: int, book_id: int, start_date: date, db: Session = Depends(get_db)):
db_loan = db.query(LoanDB).filter(
LoanDB.id_user == user_id,
LoanDB.id_book == book_id,
LoanDB.start == start_date
).first()
if db_loan is None:
raise HTTPException(status_code=404, detail="Loan not found")
try:
db.delete(db_loan)
db.commit()
return {"message": "Loan deleted successfully"}
except Exception as e:
db.rollback()
raise HTTPException(status_code=400, detail=str(e))
\ No newline at end of file
-- phpMyAdmin SQL Dump
-- version 5.2.1deb3
-- https://www.phpmyadmin.net/
--
-- Host: localhost:3306
-- Generation Time: Feb 19, 2025 at 08:30 PM
-- Server version: 10.11.8-MariaDB-0ubuntu0.24.04.1
-- PHP Version: 8.3.6
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `webapp`
--
-- --------------------------------------------------------
--
-- Table structure for table `book`
--
CREATE TABLE `book` (
`id` int(10) UNSIGNED NOT NULL,
`owner` int(10) UNSIGNED NOT NULL,
`title` varchar(80) NOT NULL,
`author` varchar(80) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Table structure for table `loan`
--
CREATE TABLE `loan` (
`id_user` int(10) UNSIGNED NOT NULL,
`id_book` int(10) UNSIGNED NOT NULL,
`status` enum('reserved','started','ended') NOT NULL DEFAULT 'reserved',
`start` date DEFAULT NULL,
`end` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
-- --------------------------------------------------------
--
-- Table structure for table `user`
--
CREATE TABLE `user` (
`id` int(10) UNSIGNED NOT NULL,
`email` varchar(50) NOT NULL,
`password` varchar(256) NOT NULL,
`role` tinyint(3) UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `book`
--
ALTER TABLE `book`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `loan`
--
ALTER TABLE `loan`
ADD UNIQUE KEY `id_user` (`id_user`,`id_book`,`start`);
--
-- Indexes for table `user`
--
ALTER TABLE `user`
ADD PRIMARY KEY (`id`),
ADD UNIQUE KEY `email` (`email`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `book`
--
ALTER TABLE `book`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `user`
--
ALTER TABLE `user`
MODIFY `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT;
--
-- Constraints for dumped tables
--
--
-- Constraints for table `loan`
--
ALTER TABLE `loan`
ADD CONSTRAINT `loan_ibfk_1` FOREIGN KEY (`id_user`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `loan_ibfk_2` FOREIGN KEY (`id_book`) REFERENCES `book` (`id`) ON DELETE CASCADE ON UPDATE CASCADE;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment