From 529cdcebb75d95f8f1e3e5596da36cdc51c8b444 Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Fri, 22 Dec 2023 15:21:26 +0100 Subject: [PATCH] feat: ask for proof type when creating (#95) * Pass type on proof upload * Add test --- app/api.py | 5 ++++- app/crud.py | 10 +++++++--- app/schemas.py | 12 +++++++----- filename.webp | 0 tests/test_api.py | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 filename.webp diff --git a/app/api.py b/app/api.py index 97417bb8..2414b70a 100644 --- a/app/api.py +++ b/app/api.py @@ -8,6 +8,7 @@ BackgroundTasks, Depends, FastAPI, + Form, HTTPException, Query, Response, @@ -28,6 +29,7 @@ from app.auth import OAuth2PasswordBearerOrAuthCookie from app.config import settings from app.db import session +from app.enums import ProofTypeEnum from app.utils import init_sentry logger = get_logger(level=settings.log_level.to_int()) @@ -242,6 +244,7 @@ def create_price( ) def upload_proof( file: UploadFile, + type: ProofTypeEnum = Form(), current_user: schemas.UserBase = Depends(get_current_user), db: Session = Depends(get_db), ): @@ -254,7 +257,7 @@ def upload_proof( This endpoint requires authentication. """ file_path, mimetype = crud.create_proof_file(file) - db_proof = crud.create_proof(db, file_path, mimetype, user=current_user) + db_proof = crud.create_proof(db, file_path, mimetype, type=type, user=current_user) return db_proof diff --git a/app/crud.py b/app/crud.py index 28426a5b..7fa7d06b 100644 --- a/app/crud.py +++ b/app/crud.py @@ -8,7 +8,7 @@ from sqlalchemy.sql import func from app import config -from app.enums import LocationOSMEnum +from app.enums import LocationOSMEnum, ProofTypeEnum from app.models import Location, Price, Product, Proof, User from app.schemas import ( LocationBase, @@ -156,7 +156,9 @@ def get_user_proofs(db: Session, user: UserBase): return db.query(Proof).filter(Proof.owner == user.user_id).all() -def create_proof(db: Session, file_path: str, mimetype: str, user: UserBase): +def create_proof( + db: Session, file_path: str, mimetype: str, type: ProofTypeEnum, user: UserBase +): """Create a proof in the database. :param db: the database session @@ -165,7 +167,9 @@ def create_proof(db: Session, file_path: str, mimetype: str, user: UserBase): :param user: the user who uploaded the file :return: the created proof """ - db_proof = Proof(file_path=file_path, mimetype=mimetype, owner=user.user_id) + db_proof = Proof( + file_path=file_path, mimetype=mimetype, type=type, owner=user.user_id + ) db.add(db_proof) db.commit() db.refresh(db_proof) diff --git a/app/schemas.py b/app/schemas.py index ab0afc35..9632037c 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -193,16 +193,18 @@ class PriceFull(PriceBase): location: LocationBase | None -class ProofCreate(BaseModel): +# class ProofCreate(BaseModel): +# file: UploadFile +# type: ProofTypeEnum + + +class ProofBase(BaseModel): model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True) + id: int file_path: str mimetype: str type: ProofTypeEnum | None = None - - -class ProofBase(ProofCreate): - id: int owner: str created: datetime.datetime diff --git a/filename.webp b/filename.webp new file mode 100644 index 00000000..e69de29b diff --git a/tests/test_api.py b/tests/test_api.py index 88d81d80..09dfc678 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -1,3 +1,5 @@ +import io + import pytest from fastapi.encoders import jsonable_encoder from fastapi.testclient import TestClient @@ -273,6 +275,42 @@ def test_get_prices_orders(): assert (response.json()["items"][0]["date"]) == "2023-10-31" +def test_create_proof(user): + # without authentication + response = client.post( + "/api/v1/proofs/upload", + ) + assert response.status_code == 401 + # with authentication but validation error (file & type missing) + response = client.post( + "/api/v1/proofs/upload", + headers={"Authorization": f"Bearer {user.token}"}, + ) + assert response.status_code == 422 + # with authentication but validation error (type missing) + response = client.post( + "/api/v1/proofs/upload", + files={"file": ("filename", (io.BytesIO(b"test")), "image/webp")}, + headers={"Authorization": f"Bearer {user.token}"}, + ) + assert response.status_code == 422 + # with authentication but validation error (file missing) + response = client.post( + "/api/v1/proofs/upload", + data={"type": "PRICE_TAG"}, + headers={"Authorization": f"Bearer {user.token}"}, + ) + assert response.status_code == 422 + # with authentication and no validation error + response = client.post( + "/api/v1/proofs/upload", + files={"file": ("filename", (io.BytesIO(b"test")), "image/webp")}, + data={"type": "PRICE_TAG"}, + headers={"Authorization": f"Bearer {user.token}"}, + ) + assert response.status_code == 201 + + def test_get_proofs(user): # without authentication response = client.get("/api/v1/proofs") @@ -283,6 +321,7 @@ def test_get_proofs(user): headers={"Authorization": f"Bearer {user.token}"}, ) assert response.status_code == 200 + assert len(response.json()) == 1 def test_get_product(product):