user creation and deletetion endpoint
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m49s
Run linting on the backend code / Build (pull_request) Successful in 46s
Run testing on the backend code / Build (pull_request) Failing after 48s
Build and release debug APK / Build APK (pull_request) Failing after 3m35s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 26s
Some checks failed
Build and deploy the backend to staging / Build and push image (pull_request) Successful in 1m49s
Run linting on the backend code / Build (pull_request) Successful in 46s
Run testing on the backend code / Build (pull_request) Failing after 48s
Build and release debug APK / Build APK (pull_request) Failing after 3m35s
Build and deploy the backend to staging / Deploy to staging (pull_request) Successful in 26s
This commit is contained in:
parent
361b2b1f42
commit
f81c28f2ac
File diff suppressed because one or more lines are too long
@ -18,7 +18,6 @@ PAYPAL_API_URL = "https://api-m.sandbox.paypal.com"
|
||||
|
||||
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')
|
||||
|
@ -11,6 +11,7 @@ from .structs.landmark import Landmark, Toilets
|
||||
from .structs.preferences import Preferences
|
||||
from .structs.linked_landmarks import LinkedLandmarks
|
||||
from .structs.trip import Trip
|
||||
from .structs.requests import UserDeleteRequest
|
||||
from .utils.landmarks_manager import LandmarkManager
|
||||
from .utils.toilets_manager import ToiletsManager
|
||||
from .optimization.optimizer import Optimizer
|
||||
@ -62,15 +63,16 @@ def new_trip(user_id: str = Body(...),
|
||||
(uuid) : The uuid of the first landmark in the optimized route
|
||||
"""
|
||||
# Check for valid user balance.
|
||||
logger.debug(f'user id: {user_id}')
|
||||
|
||||
try :
|
||||
if not supabase.check_balance(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
|
||||
return {"error": "Insufficient credits"}, 400 # Return a 400 Bad Request with an appropriate message
|
||||
except SyntaxError as se :
|
||||
raise HTTPException(status_code=400, detail=str(se)) from se
|
||||
except ValueError as ve :
|
||||
raise HTTPException(status_code=406, detail=str(ve)) from ve
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=f"Internal Server Error: {str(exc)}") from exc
|
||||
|
||||
# Check for invalid input.
|
||||
if preferences is None:
|
||||
@ -266,3 +268,46 @@ def get_toilets(location: tuple[float, float] = Query(...), radius: int = 500) -
|
||||
return toilets_list
|
||||
except KeyError as exc:
|
||||
raise HTTPException(status_code=404, detail="No toilets found") from exc
|
||||
|
||||
|
||||
@app.post("/user/create")
|
||||
def register_user(email: str = Body(...), password: str = Body(...)) -> str:
|
||||
try:
|
||||
response = supabase.supabase.auth.admin.create_user({
|
||||
"email": email,
|
||||
"password": password
|
||||
})
|
||||
|
||||
except Exception as e:
|
||||
if e.code == 'email_exists' :
|
||||
logger.error(f"Failed to create user : {str(e.code)}")
|
||||
raise HTTPException(status_code=422, detail=str(e)) from e
|
||||
logger.error(f"Failed to create user : {str(e.code)}")
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
|
||||
logger.debug(response)
|
||||
# Extract the identity_id and user_id
|
||||
# identity = response.user.id # Accessing the identity
|
||||
user_id = response.user.id
|
||||
|
||||
logger.info(f"User created successfully, ID: {user_id}")
|
||||
return user_id
|
||||
|
||||
|
||||
|
||||
@app.post("/user/delete")
|
||||
def delete_user(request: UserDeleteRequest):
|
||||
|
||||
try:
|
||||
response = supabase.supabase.auth.admin.delete_user(request.user_id)
|
||||
logger.debug(response)
|
||||
except Exception as e:
|
||||
if e.code == 'user_not_found' :
|
||||
logger.error(f"Failed to delete user : {str(e.code)}")
|
||||
raise HTTPException(status_code=404, detail=str(e)) from e
|
||||
logger.error(f"Failed to create user : {str(e.code)}")
|
||||
raise HTTPException(status_code=500, detail=str(e)) from e
|
||||
|
||||
logger.info(f"User with ID {request.user_id} deleted successfully")
|
||||
|
||||
|
||||
|
@ -21,10 +21,14 @@ class Supabase:
|
||||
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_ADMIN_KEY = secrets['SUPABASE_ADMIN_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.supabase = create_client(
|
||||
self.SUPABASE_URL,
|
||||
self.SUPABASE_ADMIN_KEY,
|
||||
options=ClientOptions(schema='public')
|
||||
)
|
||||
self.logger.debug('Supabase client initialized.')
|
||||
|
||||
|
||||
@ -47,24 +51,31 @@ class Supabase:
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.data :
|
||||
credits = response.data['credit_amount']
|
||||
self.logger.debug(f'Credits of user {user_id}: {credits}')
|
||||
# self.logger.critical(response)
|
||||
|
||||
if credits > 0:
|
||||
self.logger.info(f'Credit balance is positive. Proceeding with trip generation')
|
||||
return True
|
||||
except Exception as e:
|
||||
if e.code == '22P02' :
|
||||
self.logger.error(f"Failed querying credits : {str(e)}")
|
||||
raise SyntaxError(f"Failed querying credits : {str(e)}") from e
|
||||
if e.code == 'PGRST116' :
|
||||
self.logger.error(f"User not found : {str(e)}")
|
||||
raise ValueError(f"User not found : {str(e)}") from e
|
||||
else :
|
||||
self.logger.error(f"An unexpected error occured while checking user balance : {str(e)}")
|
||||
raise Exception(f"An unexpected error occured while checking user balance : {str(e)}") from e
|
||||
|
||||
self.logger.warning(f'Insufficient balance. Trip generation cannot be granted')
|
||||
return False
|
||||
# Proceed to check the user's credit balance
|
||||
credits = response.data['credit_amount']
|
||||
self.logger.debug(f'Credits of user {user_id}: {credits}')
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
if credits > 0:
|
||||
self.logger.info(f'Credit balance is positive for user {user_id}. Proceeding with trip generation.')
|
||||
return True
|
||||
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail="Error retrieving credit balance") from exc
|
||||
self.logger.warning(f'Insufficient balance for user {user_id}. Trip generation cannot proceed.')
|
||||
return False
|
||||
|
||||
|
||||
|
||||
def decrement_credit_balance(self, user_id: str) -> bool:
|
||||
"""
|
||||
@ -82,32 +93,36 @@ class Supabase:
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.data :
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits - 1
|
||||
except Exception as e:
|
||||
if e.code == '22P02' :
|
||||
self.logger.error(f"Failed decrementing credits : {str(e)}")
|
||||
raise SyntaxError(f"Failed decrementing credits : {str(e)}") from e
|
||||
if e.code == 'PGRST116' :
|
||||
self.logger.error(f"User not found : {str(e)}")
|
||||
raise ValueError(f"User not found : {str(e)}") from e
|
||||
else :
|
||||
self.logger.error(f"An unexpected error occured while decrementing user balance : {str(e)}")
|
||||
raise Exception(f"An unexpected error occured while decrementing user balance : {str(e)}") from e
|
||||
|
||||
# Update the user's credits in the table
|
||||
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.data:
|
||||
self.logger.debug(f'Credit balance successfully decremented.')
|
||||
return True
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail="Error decrementing credit balance.")
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits - 1
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
# Update the user's credits in the table
|
||||
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.data:
|
||||
self.logger.debug(f'Credit balance successfully decremented.')
|
||||
return True
|
||||
else:
|
||||
raise Exception("Error decrementing credit balance.")
|
||||
|
||||
except Exception:
|
||||
# Handle exceptions (like if the user ID doesn't exist or there are database issues)
|
||||
raise HTTPException(status_code=500, detail="Error decrementing credit balance")
|
||||
|
||||
def increment_credit_balance(self, user_id: str) -> bool:
|
||||
"""
|
||||
@ -125,29 +140,32 @@ class Supabase:
|
||||
.single()
|
||||
.execute()
|
||||
)
|
||||
# Check if the response was successful and contains data
|
||||
if response.data :
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits + 1
|
||||
except Exception as e:
|
||||
if e.code == '22P02' :
|
||||
self.logger.error(f"Failed incrementing credits : {str(e)}")
|
||||
raise SyntaxError(f"Failed incrementing credits : {str(e)}") from e
|
||||
if e.code == 'PGRST116' :
|
||||
self.logger.error(f"User not found : {str(e)}")
|
||||
raise ValueError(f"User not found : {str(e)}") from e
|
||||
else :
|
||||
self.logger.error(f"An unexpected error occured while incrementing user balance : {str(e)}")
|
||||
raise Exception(f"An unexpected error occured while incrementing user balance : {str(e)}") from e
|
||||
|
||||
# Update the user's credits in the table
|
||||
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.data:
|
||||
self.logger.debug(f'Credit balance successfully incremented.')
|
||||
return True
|
||||
else:
|
||||
raise HTTPException(status_code=500, detail="Error incrementing credit balance.")
|
||||
current_credits = response.data['credit_amount']
|
||||
updated_credits = current_credits + 1
|
||||
|
||||
# If user or credits not found, raise a 404 error
|
||||
raise HTTPException(status_code=404, detail="User data not found.")
|
||||
# Update the user's credits in the table
|
||||
update_response = (
|
||||
self.supabase.table('credits')
|
||||
.update({'credit_amount': updated_credits})
|
||||
.eq('id', user_id)
|
||||
.execute()
|
||||
)
|
||||
|
||||
except Exception:
|
||||
# Handle exceptions (like if the user ID doesn't exist or there are database issues)
|
||||
raise HTTPException(status_code=500, detail="Error incrementing credit balance")
|
||||
# Check if the update was successful
|
||||
if update_response.data:
|
||||
self.logger.debug(f'Credit balance successfully decremented.')
|
||||
return True
|
||||
else:
|
||||
raise Exception("Error decrementing credit balance.")
|
||||
|
4
backend/src/structs/requests.py
Normal file
4
backend/src/structs/requests.py
Normal file
@ -0,0 +1,4 @@
|
||||
from pydantic import BaseModel
|
||||
|
||||
class UserDeleteRequest(BaseModel):
|
||||
user_id: str
|
@ -62,3 +62,32 @@ def test_input(invalid_client, start, preferences, status_code): # pylint: dis
|
||||
}
|
||||
)
|
||||
assert response.status_code == status_code
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"user_id,status_code",
|
||||
[
|
||||
# No user id :
|
||||
({}, 422),
|
||||
("invalid_user_id", 400),
|
||||
# ("12345678-1234-5678-1234-567812345678", 406)
|
||||
]
|
||||
)
|
||||
def test_input(invalid_client, user_id, status_code): # pylint: disable=redefined-outer-name
|
||||
"""
|
||||
Test new trip creation with invalid user ID.
|
||||
"""
|
||||
response = invalid_client.post(
|
||||
"/trip/new",
|
||||
json={
|
||||
"user_id": user_id,
|
||||
"preferences": {"sightseeing": {"type": "sightseeing", "score": 5},
|
||||
"nature": {"type": "nature", "score": 0},
|
||||
"shopping": {"type": "shopping", "score": 0},
|
||||
"max_time_minute": 20,
|
||||
"detour_tolerance_minute": 0},
|
||||
"start": [48.084588, 7.280405]
|
||||
}
|
||||
)
|
||||
assert response.status_code == status_code
|
||||
|
68
backend/src/tests/test_user.py
Normal file
68
backend/src/tests/test_user.py
Normal file
@ -0,0 +1,68 @@
|
||||
"""Collection of tests to ensure correct handling of user data."""
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
import pytest
|
||||
|
||||
from ..main import app
|
||||
|
||||
TEST_EMAIL = "dummy@example.com"
|
||||
TEST_PW = "DummyPassword123"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def client():
|
||||
"""Client used to call the app."""
|
||||
return TestClient(app)
|
||||
|
||||
|
||||
def test_user_handling(client) :
|
||||
"""
|
||||
Test the creation of a new user.
|
||||
"""
|
||||
# Create a new user
|
||||
response = client.post(
|
||||
"/user/create",
|
||||
json={
|
||||
"email": TEST_EMAIL,
|
||||
"password": TEST_PW
|
||||
}
|
||||
)
|
||||
# Verify user has been created
|
||||
assert response.status_code == 200
|
||||
user_id = response.json()
|
||||
|
||||
# # Create same user again to raise an error
|
||||
response = client.post(
|
||||
"/user/create",
|
||||
json={
|
||||
"email": TEST_EMAIL,
|
||||
"password": TEST_PW
|
||||
}
|
||||
)
|
||||
# Verify user already exists
|
||||
assert response.status_code == 422
|
||||
|
||||
# Delete the user.
|
||||
response = client.post(
|
||||
"/user/delete",
|
||||
json={
|
||||
"user_id": user_id
|
||||
}
|
||||
)
|
||||
print(response)
|
||||
# Verify user has been deleted
|
||||
assert response.status_code == 200, "Failed to delete dummy user."
|
||||
|
||||
|
||||
# Delete the user again to raise an error
|
||||
response = client.post(
|
||||
"/user/delete",
|
||||
json={
|
||||
"user_id": user_id
|
||||
}
|
||||
)
|
||||
print(response)
|
||||
# Verify user has been deleted
|
||||
assert response.status_code == 404, "Failed to delete dummy user."
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user