from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File from sqlalchemy.orm import Session from sqlalchemy import func from typing import List from .. import models, schemas, auth from ..database import get_db router = APIRouter( prefix="/items", tags=["Items"] ) @router.get("/stats") def read_item_stats( db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Statistici iteme — doar utilizatori autentificati.""" total_categories = db.query(models.Category).count() total_items = db.query(models.Item).count() # Count items per category string items_per_category = db.query(models.Item.category, func.count(models.Item.id))\ .group_by(models.Item.category).all() return { "total_categories": total_categories, "total_items": total_items, "items_distribution": {cat: count for cat, count in items_per_category if cat} } @router.get("/", response_model=List[schemas.Item]) def read_items( skip: int = 0, limit: int = 100, db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Lista iteme — doar utilizatori autentificati.""" items = db.query(models.Item).offset(skip).limit(limit).all() return items @router.get("/{item_id}", response_model=schemas.Item) def read_item( item_id: int, db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Obține item — doar utilizatori autentificati.""" item = db.query(models.Item).filter(models.Item.id == item_id).first() if item is None: raise HTTPException(status_code=404, detail="Item not found") return item _ALLOWED_IMAGE_TYPES = {"image/jpeg", "image/png", "image/webp", "image/gif"} _MAX_IMAGE_SIZE = 10 * 1024 * 1024 # 10 MB @router.post("/extract-label") async def extract_label( file: UploadFile = File(...), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Extragere etichetă din imagine — doar utilizatori autentificati. [H-02] Rate limit pe endpoint.""" from ..ai_vision import extract_label_info # [SECURITY FIX H-03] Validare tip MIME și dimensiune maximă if file.content_type not in _ALLOWED_IMAGE_TYPES: raise HTTPException( status_code=status.HTTP_415_UNSUPPORTED_MEDIA_TYPE, detail=f"Tip fișier nepermis: {file.content_type}. Acceptat: {', '.join(_ALLOWED_IMAGE_TYPES)}" ) contents = await file.read() if len(contents) > _MAX_IMAGE_SIZE: raise HTTPException( status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE, detail="Fișierul depășește limita de 10MB." ) result = extract_label_info(contents) return result @router.post("/", response_model=schemas.Item, status_code=status.HTTP_201_CREATED) def create_item( item: schemas.ItemCreate, db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Creare item — doar utilizatori autentificati. [M-02] user_id din token.""" # Check if barcode exists db_item = db.query(models.Item).filter(models.Item.barcode == item.barcode).first() if db_item: raise HTTPException(status_code=400, detail="Barcode already registered") db_item = models.Item(**item.model_dump()) db.add(db_item) db.commit() db.refresh(db_item) # Audit log the creation — [M-02] user_id din token, nu din body audit = models.AuditLog( user_id=current_user.sub, action="CREATE_ITEM", target_item_id=db_item.id, quantity_change=item.quantity ) db.add(audit) db.commit() return db_item @router.put("/{item_id}", response_model=schemas.Item) def update_item( item_id: int, item: schemas.ItemCreate, db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Actualizare item — doar utilizatori autentificati.""" db_item = db.query(models.Item).filter(models.Item.id == item_id).first() if not db_item: raise HTTPException(status_code=404, detail="Item not found") update_data = item.model_dump(exclude_unset=True) for key, value in update_data.items(): setattr(db_item, key, value) db.commit() db.refresh(db_item) return db_item @router.delete("/{item_id}") def delete_item( item_id: int, db: Session = Depends(get_db), current_user: auth.TokenData = Depends(auth.get_current_user) ): """[C-01] Ștergere item — doar utilizatori autentificati.""" db_item = db.query(models.Item).filter(models.Item.id == item_id).first() if not db_item: raise HTTPException(status_code=404, detail="Item not found") db.delete(db_item) db.commit() return {"message": "Item deleted successfully"}