corrected supabase api communication
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 2m26s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 49s
Build and release debug APK / Build APK (pull_request) Failing after 3m22s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 25s
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 2m26s
Run linting on the backend code / Build (pull_request) Successful in 27s
Run testing on the backend code / Build (pull_request) Failing after 49s
Build and release debug APK / Build APK (pull_request) Failing after 3m22s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 25s
This commit is contained in:
@@ -12,13 +12,13 @@ LANDMARK_PARAMETERS_PATH = PARAMETERS_DIR / 'landmark_parameters.yaml'
|
||||
OPTIMIZER_PARAMETERS_PATH = PARAMETERS_DIR / 'optimizer_parameters.yaml'
|
||||
|
||||
|
||||
PAYPAL_CLIENT_ID = 0 # os.getenv("your-paypal-client-id")
|
||||
PAYPAL_SECRET = 0 # os.getenv("your-paypal-secret")
|
||||
PAYPAL_API_URL = 0 # "https://api-m.sandbox.paypal.com"
|
||||
PAYPAL_CLIENT_ID = os.getenv("future-paypal-client-id", None)
|
||||
PAYPAL_SECRET = os.getenv("future-paypal-secret", None)
|
||||
PAYPAL_API_URL = "https://api-m.sandbox.paypal.com"
|
||||
|
||||
SUPABASE_URL = os.environ["SUPABASE_URL"]
|
||||
SUPABASE_KEY = os.environ["SUPABASE_API_KEY"]
|
||||
SUPABASE_TEST_USER_ID = os.environ["SUPABASE_TEST_USER_ID"]
|
||||
SUPABASE_URL = os.getenv("SUPABASE_URL", None)
|
||||
SUPABASE_KEY = os.getenv("SUPABASE_API_KEY", None)
|
||||
SUPABASE_TEST_USER_ID = os.getenv("SUPABASE_TEST_USER_ID", None)
|
||||
|
||||
|
||||
cache_dir_string = os.getenv('OSM_CACHE_DIR', './cache')
|
||||
|
@@ -1,9 +1,10 @@
|
||||
"""Main app for backend api"""
|
||||
|
||||
import logging
|
||||
import traceback
|
||||
import time
|
||||
from contextlib import asynccontextmanager
|
||||
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query
|
||||
from fastapi import FastAPI, HTTPException, BackgroundTasks, Query, Body
|
||||
|
||||
from .logging_config import configure_logging
|
||||
from .structs.landmark import Landmark, Toilets
|
||||
@@ -16,7 +17,7 @@ from .optimization.optimizer import Optimizer
|
||||
from .optimization.refiner import Refiner
|
||||
from .overpass.overpass import fill_cache
|
||||
from .cache import client as cache_client
|
||||
from .payments.payment_routes import router as payment_router
|
||||
# from .payments.payment_routes import router as payment_router
|
||||
from .payments.supabase import Supabase
|
||||
|
||||
|
||||
@@ -41,14 +42,14 @@ app = FastAPI(lifespan=lifespan)
|
||||
|
||||
|
||||
# Include the payment routes
|
||||
app.include_router(payment_router, prefix="/payments")
|
||||
# app.include_router(payment_router, prefix="/payments")
|
||||
|
||||
|
||||
@app.post("/trip/new")
|
||||
def new_trip(user_id: str,
|
||||
preferences: Preferences,
|
||||
start: tuple[float, float],
|
||||
end: tuple[float, float] | None = None,
|
||||
def new_trip(user_id: str = Body(...),
|
||||
preferences: Preferences = Body(...),
|
||||
start: tuple[float, float] = Body(...),
|
||||
end: tuple[float, float] | None = Body(None),
|
||||
background_tasks: BackgroundTasks = None) -> Trip:
|
||||
"""
|
||||
Main function to call the optimizer.
|
||||
@@ -61,7 +62,15 @@ def new_trip(user_id: str,
|
||||
(uuid) : The uuid of the first landmark in the optimized route
|
||||
"""
|
||||
# Check for valid user balance.
|
||||
supabase.check_balance(user_id=user_id)
|
||||
logger.debug(f'user id: {user_id}')
|
||||
|
||||
try :
|
||||
if not supabase.check_balance(user_id=user_id) :
|
||||
logger.warning('Insufficient credits to perform this action.')
|
||||
return None
|
||||
except Exception as exc :
|
||||
traceback.print_exc()
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
|
||||
# Check for invalid input.
|
||||
if preferences is None:
|
||||
@@ -150,7 +159,7 @@ def new_trip(user_id: str,
|
||||
logger.debug('Detailed trip :\n\t' + '\n\t'.join(f'{landmark}' for landmark in refined_tour))
|
||||
|
||||
background_tasks.add_task(fill_cache)
|
||||
supabase.increment_credit_balance(user_id=user_id)
|
||||
supabase.decrement_credit_balance(user_id=user_id)
|
||||
|
||||
return trip
|
||||
|
||||
|
@@ -1,15 +1,34 @@
|
||||
import os
|
||||
import logging
|
||||
import yaml
|
||||
from fastapi import HTTPException, status
|
||||
from supabase import create_client, Client
|
||||
from ..constants import SUPABASE_URL, SUPABASE_KEY
|
||||
from supabase import create_client, Client, ClientOptions
|
||||
|
||||
from ..constants import PARAMETERS_DIR
|
||||
|
||||
# Silence the supabase logger
|
||||
logging.getLogger("httpx").setLevel(logging.CRITICAL)
|
||||
logging.getLogger("hpack").setLevel(logging.CRITICAL)
|
||||
logging.getLogger("httpcore").setLevel(logging.CRITICAL)
|
||||
|
||||
|
||||
class Supabase:
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def __init__(self):
|
||||
# Initialize Supabase client
|
||||
print(SUPABASE_URL)
|
||||
self.supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
|
||||
|
||||
with open(os.path.join(PARAMETERS_DIR, 'secrets.yaml')) as f:
|
||||
secrets = yaml.safe_load(f)
|
||||
self.SUPABASE_URL = secrets['SUPABASE_URL']
|
||||
self.SUPABASE_KEY = secrets['SUPABASE_API_KEY']
|
||||
self.SUPABASE_TEST_USER_ID = secrets['SUPABASE_TEST_USER_ID']
|
||||
|
||||
self.supabase: Client = create_client(self.SUPABASE_URL, self.SUPABASE_KEY, options=ClientOptions(schema='public'))
|
||||
self.logger.debug('Supabase client initialized.')
|
||||
|
||||
|
||||
def check_balance(self, user_id: str):
|
||||
def check_balance(self, user_id: str) -> bool:
|
||||
"""
|
||||
Checks if the user has enough 'credit' for generating a new trip.
|
||||
|
||||
@@ -21,22 +40,30 @@ class Supabase:
|
||||
"""
|
||||
try:
|
||||
# Query the public.credits table to get the user's credits
|
||||
response = self.supabase.table('credits').select('credits').eq('user_id', user_id).single().execute()
|
||||
|
||||
response = (
|
||||
self.supabase.table("credits")
|
||||
.select('*')
|
||||
.eq('id', user_id)
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.get('data') and 'credits' in response['data']:
|
||||
credits = response['data']['credits']
|
||||
|
||||
if credits <= 0:
|
||||
raise HTTPException(status_code=403, detail="Insufficient credits to perform this action.")
|
||||
if response.data :
|
||||
credits = response.data['credit_amount']
|
||||
self.logger.debug(f'Credits of user {user_id}: {credits}')
|
||||
|
||||
if credits > 0:
|
||||
self.logger.info(f'Credit balance is positive. Proceeding with trip generation')
|
||||
return True
|
||||
|
||||
self.logger.warning(f'Insufficient balance. Trip generation cannot be granted')
|
||||
return False
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User data not found.")
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
|
||||
except Exception:
|
||||
# Handle exceptions (like if the user ID doesn't exist or database issues)
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error retrieving credit balance")
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail="Error retrieving credit balance") from exc
|
||||
|
||||
|
||||
def decrement_credit_balance(self, user_id: str) -> bool:
|
||||
@@ -48,30 +75,39 @@ class Supabase:
|
||||
"""
|
||||
try:
|
||||
# Query the public.credits table to get the user's current credits
|
||||
response = self.supabase.table('credits').select('credits').eq('user_id', user_id).single().execute()
|
||||
|
||||
response = (
|
||||
self.supabase.table("credits")
|
||||
.select('*')
|
||||
.eq('id', user_id)
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.get('data') and 'credits' in response['data']:
|
||||
current_credits = response['data']['credits']
|
||||
# Decrement the credit balance by 1
|
||||
if response.data :
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits - 1
|
||||
|
||||
# Update the user's credits in the table
|
||||
update_response = self.supabase.table('credits').update({'credits': updated_credits}).eq('user_id', user_id).execute()
|
||||
update_response = (
|
||||
self.supabase.table('credits')
|
||||
.update({'credit_amount': updated_credits})
|
||||
.eq('id', user_id)
|
||||
.execute()
|
||||
)
|
||||
|
||||
# Check if the update was successful
|
||||
if update_response.get('status_code') == 200:
|
||||
if update_response.data:
|
||||
self.logger.debug(f'Credit balance successfully decremented.')
|
||||
return True
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error updating credit balance.")
|
||||
raise HTTPException(status_code=500, detail="Error decrementing credit balance.")
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User data not found.")
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
|
||||
except Exception:
|
||||
# Handle exceptions (like if the user ID doesn't exist or there are database issues)
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error updating credit balance")
|
||||
|
||||
raise HTTPException(status_code=500, detail="Error decrementing credit balance")
|
||||
|
||||
def increment_credit_balance(self, user_id: str) -> bool:
|
||||
"""
|
||||
@@ -82,26 +118,36 @@ class Supabase:
|
||||
"""
|
||||
try:
|
||||
# Query the public.credits table to get the user's current credits
|
||||
response = self.supabase.table('credits').select('credits').eq('user_id', user_id).single().execute()
|
||||
|
||||
response = (
|
||||
self.supabase.table("credits")
|
||||
.select('*')
|
||||
.eq('id', user_id)
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.get('data') and 'credits' in response['data']:
|
||||
current_credits = response['data']['credits']
|
||||
# Increment the credit balance by 1
|
||||
if response.data :
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits + 1
|
||||
|
||||
# Update the user's credits in the table
|
||||
update_response = self.supabase.table('credits').update({'credits': updated_credits}).eq('user_id', user_id).execute()
|
||||
update_response = (
|
||||
self.supabase.table('credits')
|
||||
.update({'credit_amount': updated_credits})
|
||||
.eq('id', user_id)
|
||||
.execute()
|
||||
)
|
||||
|
||||
# Check if the update was successful
|
||||
if update_response.get('status_code') == 200:
|
||||
if update_response.data:
|
||||
self.logger.debug(f'Credit balance successfully incremented.')
|
||||
return True
|
||||
else:
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error updating credit balance.")
|
||||
raise HTTPException(status_code=500, detail="Error incrementing credit balance.")
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="User data not found.")
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
|
||||
except Exception:
|
||||
# Handle exceptions (like if the user ID doesn't exist or there are database issues)
|
||||
raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Error updating credit balance")
|
||||
raise HTTPException(status_code=500, detail="Error incrementing credit balance")
|
||||
|
@@ -1,13 +1,16 @@
|
||||
"""Collection of tests to ensure correct implementation and track progress. """
|
||||
import time
|
||||
import logging
|
||||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from .test_utils import load_trip_landmarks, log_trip_details
|
||||
from ..main import app
|
||||
from ..constants import SUPABASE_TEST_USER_ID
|
||||
from ..payments.supabase import Supabase
|
||||
|
||||
supabase = Supabase()
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
"""Client used to call the app."""
|
||||
@@ -24,24 +27,25 @@ def test_turckheim(client, request): # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
start_time = time.time() # Start timer
|
||||
duration_minutes = 20
|
||||
logger.debug('Running test in Turckheim')
|
||||
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 0},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 0},
|
||||
"max_time_minute": duration_minutes,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.084588, 7.280405]
|
||||
# "start": [45.74445023349939, 4.8222687890538865]
|
||||
# "start": [45.75156398104873, 4.827154464827647]
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
logger.debug(f'API response : {result}')
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
|
||||
@@ -80,7 +84,7 @@ def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -90,8 +94,7 @@ def test_bellecour(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -123,7 +126,7 @@ def test_cologne(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -133,8 +136,7 @@ def test_cologne(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -167,7 +169,7 @@ def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -177,8 +179,7 @@ def test_strasbourg(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -211,7 +212,7 @@ def test_zurich(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -221,8 +222,7 @@ def test_zurich(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -255,7 +255,7 @@ def test_paris(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -265,8 +265,7 @@ def test_paris(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -299,7 +298,7 @@ def test_new_york(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 5},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -309,8 +308,7 @@ def test_new_york(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
@@ -343,7 +341,7 @@ def test_shopping(client, request) : # pylint: disable=redefined-outer-name
|
||||
response = client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": SUPABASE_TEST_USER_ID,
|
||||
"user_id": supabase.SUPABASE_TEST_USER_ID,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 0},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 5},
|
||||
@@ -353,8 +351,7 @@ def test_shopping(client, request) : # pylint: disable=redefined-outer-name
|
||||
}
|
||||
)
|
||||
result = response.json()
|
||||
supabase = Supabase()
|
||||
supabase.increment_credit_balance(user_id=SUPABASE_TEST_USER_ID)
|
||||
supabase.increment_credit_balance(user_id=supabase.SUPABASE_TEST_USER_ID)
|
||||
landmarks = load_trip_landmarks(client, result['first_landmark_uuid'])
|
||||
|
||||
# Get computation time
|
||||
|
Reference in New Issue
Block a user