Skip to content

Commit

Permalink
feat(API): Allow anonymous users to upload proofs (#607)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphodn authored Dec 6, 2024
1 parent e4bfe68 commit 0c68bf8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 6 deletions.
9 changes: 9 additions & 0 deletions config/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,22 @@

GOOGLE_CLOUD_VISION_API_KEY = os.getenv("GOOGLE_CLOUD_VISION_API_KEY")


# Google Gemini API
# ------------------------------------------------------------------------------

GOOGLE_GEMINI_API_KEY = os.getenv("GOOGLE_GEMINI_API_KEY")


# Triton Inference Server (ML)
# ------------------------------------------------------------------------------

TRITON_URI = os.getenv("TRITON_URI", "localhost:5504")
ENABLE_ML_PREDICTIONS = os.getenv("ENABLE_ML_PREDICTIONS") == "True"


# Open Food Facts
# ------------------------------------------------------------------------------

# https://world.openfoodfacts.org/contributor/openfoodfacts-contributors
ANONYMOUS_USER_ID = "openfoodfacts-contributors"
27 changes: 24 additions & 3 deletions open_prices/api/proofs/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from decimal import Decimal
from io import BytesIO

from django.conf import settings
from django.test import TestCase
from django.urls import reverse
from PIL import Image
Expand Down Expand Up @@ -183,17 +184,37 @@ def tearDown(self):
[p.delete() for p in Proof.objects.all()]
return super().tearDown()

def test_proof_create(self):
def test_proof_create_anonymous(self):
# wrong endpoint
response = self.client.post(reverse("api:proofs-list"), self.data)
self.assertEqual(response.status_code, 403) # 405 ?
# anonymous
response = self.client.post(self.url, self.data)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 201)
self.assertTrue(response.data["file_path"] is not None)
self.assertTrue(response.data["image_thumb_path"] is None) # .bin
self.assertEqual(response.data["currency"], "EUR")
self.assertEqual(response.data["price_count"], 0) # ignored
self.assertEqual(response.data["owner"], settings.ANONYMOUS_USER_ID)
self.assertTrue("source" not in response.data)
self.assertEqual(Proof.objects.last().source, "API") # default value
# wrong token
response = self.client.post(
self.url,
self.data,
headers={"Authorization": f"Bearer {self.user_session.token}X"},
)
self.assertEqual(response.status_code, 403)
self.assertEqual(response.status_code, 201) # 403 ?
self.assertEqual(response.data["owner"], settings.ANONYMOUS_USER_ID)

def test_proof_create_authenticated(self):
# wrong endpoint
response = self.client.post(
reverse("api:proofs-list"),
self.data,
headers={"Authorization": f"Bearer {self.user_session.token}"},
)
self.assertEqual(response.status_code, 405)
# authenticated
response = self.client.post(
self.url,
Expand Down
13 changes: 10 additions & 3 deletions open_prices/api/proofs/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import PIL.Image
from django.conf import settings
from django_filters.rest_framework import DjangoFilterBackend
from drf_spectacular.utils import extend_schema
from rest_framework import filters, mixins, status, viewsets
Expand Down Expand Up @@ -75,6 +76,7 @@ def destroy(self, request: Request, *args, **kwargs) -> Response:
methods=["POST"],
url_path="upload",
parser_classes=[MultiPartParser],
permission_classes=[], # allow anonymous upload
)
def upload(self, request: Request) -> Response:
# build proof
Expand All @@ -97,11 +99,16 @@ def upload(self, request: Request) -> Response:
# validate
serializer = ProofCreateSerializer(data=proof_create_data)
serializer.is_valid(raise_exception=True)
# get source
# get owner & source
owner = (
self.request.user.user_id
if self.request.user.is_authenticated
else settings.ANONYMOUS_USER_ID
)
source = get_source_from_request(self.request)
# save
proof = serializer.save(owner=self.request.user.user_id, source=source)
# return full proof
proof = serializer.save(owner=owner, source=source)
# return the full proof
return Response(ProofFullSerializer(proof).data, status=status.HTTP_201_CREATED)

@extend_schema(request=ProofProcessWithGeminiSerializer)
Expand Down

0 comments on commit 0c68bf8

Please sign in to comment.