From 6c297b5e810910537cd7dc71ecde049609c77a93 Mon Sep 17 00:00:00 2001 From: "cartsnitch-engineer[bot]" <269717931+cartsnitch-engineer[bot]@users.noreply.github.com> Date: Fri, 3 Apr 2026 13:34:21 +0000 Subject: [PATCH] fix: correct email-in-address format, remove dead code, update tests (#110) - Fix email format in AuthService.get_email_in_address to use receipts+{token}@receipts.cartsnitch.com (was broken: @email.cartsnitch.com) - Remove dead EmailInAddressResponse class and GET /auth/me/email-in-address endpoint from auth/routes.py (endpoint moved to routes/user.py) - Add instructions field to EmailInAddressResponse schema - Update routes/user.py to include instructions in the response - Update test URLs from /auth/me/email-in-address to /api/v1/me/email-in-address Co-authored-by: CartSnitch Engineer Bot Co-authored-by: Paperclip --- api/src/cartsnitch_api/auth/routes.py | 25 --------------------- api/src/cartsnitch_api/routes/user.py | 8 ++++++- api/src/cartsnitch_api/schemas.py | 1 + api/src/cartsnitch_api/services/auth.py | 2 +- api/tests/test_e2e/test_email_in_address.py | 10 ++++----- 5 files changed, 14 insertions(+), 32 deletions(-) diff --git a/api/src/cartsnitch_api/auth/routes.py b/api/src/cartsnitch_api/auth/routes.py index 1400d7a..1c7cc63 100644 --- a/api/src/cartsnitch_api/auth/routes.py +++ b/api/src/cartsnitch_api/auth/routes.py @@ -22,11 +22,6 @@ from cartsnitch_api.services.auth import AuthService router = APIRouter(prefix="/auth", tags=["auth"]) -class EmailInAddressResponse(BaseModel): - email_address: str - instructions: str - - @router.get("/me", response_model=UserResponse) async def get_me( user_id: str = Depends(get_current_user), @@ -70,23 +65,3 @@ async def delete_me( raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" ) from None - - -@router.get("/me/email-in-address", response_model=EmailInAddressResponse) -async def get_email_in_address( - user_id: str = Depends(get_current_user), - db: AsyncSession = Depends(get_db), -): - result = await db.execute(select(User.email_inbound_token).where(User.id == user_id)) - token = result.scalar_one_or_none() - if not token: - raise HTTPException( - status_code=status.HTTP_404_NOT_FOUND, detail="Email inbound token not found" - ) from None - return EmailInAddressResponse( - email_address=f"receipts+{token}@receipts.cartsnitch.com", - instructions=( - "Forward your digital receipt emails to this address. " - "We currently support Meijer, Kroger, and Target receipt emails." - ), - ) diff --git a/api/src/cartsnitch_api/routes/user.py b/api/src/cartsnitch_api/routes/user.py index 18da0f1..541cc85 100644 --- a/api/src/cartsnitch_api/routes/user.py +++ b/api/src/cartsnitch_api/routes/user.py @@ -19,7 +19,13 @@ async def get_email_in_address( svc = AuthService(db) try: email_address = await svc.get_email_in_address(user_id) - return EmailInAddressResponse(email_address=email_address) + return EmailInAddressResponse( + email_address=email_address, + instructions=( + "Forward your digital receipt emails to this address. " + "We currently support Meijer, Kroger, and Target receipt emails." + ), + ) except LookupError: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="User not found" diff --git a/api/src/cartsnitch_api/schemas.py b/api/src/cartsnitch_api/schemas.py index 703b10c..18c5cf5 100644 --- a/api/src/cartsnitch_api/schemas.py +++ b/api/src/cartsnitch_api/schemas.py @@ -24,6 +24,7 @@ class UserResponse(BaseModel): class EmailInAddressResponse(BaseModel): email_address: str + instructions: str # ---------- Stores ---------- diff --git a/api/src/cartsnitch_api/services/auth.py b/api/src/cartsnitch_api/services/auth.py index 6cbf3d3..b08369f 100644 --- a/api/src/cartsnitch_api/services/auth.py +++ b/api/src/cartsnitch_api/services/auth.py @@ -76,4 +76,4 @@ class AuthService: if not user: raise LookupError("User not found") - return f"{user.email_inbound_token}@email.cartsnitch.com" + return f"receipts+{user.email_inbound_token}@receipts.cartsnitch.com" diff --git a/api/tests/test_e2e/test_email_in_address.py b/api/tests/test_e2e/test_email_in_address.py index 7886572..ad3b414 100644 --- a/api/tests/test_e2e/test_email_in_address.py +++ b/api/tests/test_e2e/test_email_in_address.py @@ -1,4 +1,4 @@ -"""Tests for GET /auth/me/email-in-address endpoint.""" +"""Tests for GET /api/v1/me/email-in-address endpoint.""" import pytest from httpx import AsyncClient @@ -8,7 +8,7 @@ from httpx import AsyncClient async def test_get_email_in_address_authenticated(client: AsyncClient, auth_headers: dict): """Authenticated user gets their email-in address.""" response = await client.get( - "/auth/me/email-in-address", + "/api/v1/me/email-in-address", headers=auth_headers, ) @@ -27,7 +27,7 @@ async def test_get_email_in_address_authenticated(client: AsyncClient, auth_head @pytest.mark.asyncio async def test_get_email_in_address_unauthenticated(client: AsyncClient): """Unauthenticated request returns 401.""" - response = await client.get("/auth/me/email-in-address") + response = await client.get("/api/v1/me/email-in-address") assert response.status_code == 401 @@ -35,7 +35,7 @@ async def test_get_email_in_address_unauthenticated(client: AsyncClient): async def test_get_email_in_address_invalid_token(client: AsyncClient): """Invalid JWT token returns 401.""" response = await client.get( - "/auth/me/email-in-address", + "/api/v1/me/email-in-address", headers={"Authorization": "Bearer invalid-token-xyz"}, ) assert response.status_code == 401 @@ -45,7 +45,7 @@ async def test_get_email_in_address_invalid_token(client: AsyncClient): async def test_email_address_format(client: AsyncClient, auth_headers: dict): """Email address format is receipts+{22-char-urlsafe-token}@receipts.cartsnitch.com.""" response = await client.get( - "/auth/me/email-in-address", + "/api/v1/me/email-in-address", headers=auth_headers, )