fix(api): revert auth/type regressions from standalone sync, keep email-in feature only
- Revert auth/dependencies.py to cookie+Bearer dual auth with str user IDs - Add GET /auth/me/email-in-address endpoint for receipt email routing - Update User model: add email_inbound_token, change id/store_id/user_id to str - Update AuthService and UserResponse to use str user IDs - Update route count test: 33 -> 34 routes - Restore e2e test for email-in-address endpoint Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
@@ -5,8 +5,6 @@ handled by the Better-Auth service (auth/). This service provides
|
||||
user lookup and profile update operations for the API gateway.
|
||||
"""
|
||||
|
||||
from uuid import UUID
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
@@ -15,14 +13,10 @@ class AuthService:
|
||||
def __init__(self, db: AsyncSession) -> None:
|
||||
self.db = db
|
||||
|
||||
async def get_user(self, user_id: UUID) -> dict:
|
||||
async def get_user(self, user_id: str) -> dict:
|
||||
from cartsnitch_api.models import User
|
||||
|
||||
# Use str() to ensure consistent string comparison for UUID columns
|
||||
# (works with both SQLite VARCHAR and Postgres UUID storage)
|
||||
result = await self.db.execute(
|
||||
select(User).where(User.id == str(user_id))
|
||||
)
|
||||
result = await self.db.execute(select(User).where(User.id == user_id))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise LookupError("User not found")
|
||||
@@ -34,11 +28,10 @@ class AuthService:
|
||||
"created_at": user.created_at,
|
||||
}
|
||||
|
||||
async def update_user(self, user_id: UUID, **fields) -> dict:
|
||||
async def update_user(self, user_id: str, **fields) -> dict:
|
||||
from cartsnitch_api.models import User
|
||||
|
||||
user_id_str = str(user_id)
|
||||
result = await self.db.execute(select(User).where(User.id == user_id_str))
|
||||
result = await self.db.execute(select(User).where(User.id == user_id))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise LookupError("User not found")
|
||||
@@ -47,7 +40,7 @@ class AuthService:
|
||||
user.display_name = fields["display_name"]
|
||||
if "email" in fields and fields["email"] is not None:
|
||||
existing = await self.db.execute(
|
||||
select(User).where(User.email == fields["email"], User.id != user_id_str)
|
||||
select(User).where(User.email == fields["email"], User.id != user_id)
|
||||
)
|
||||
if existing.scalar_one_or_none():
|
||||
raise ValueError("Email already in use")
|
||||
@@ -63,31 +56,13 @@ class AuthService:
|
||||
"created_at": user.created_at,
|
||||
}
|
||||
|
||||
async def delete_user(self, user_id: UUID) -> None:
|
||||
async def delete_user(self, user_id: str) -> None:
|
||||
from cartsnitch_api.models import User
|
||||
|
||||
result = await self.db.execute(select(User).where(User.id == str(user_id)))
|
||||
result = await self.db.execute(select(User).where(User.id == user_id))
|
||||
user = result.scalar_one_or_none()
|
||||
if not user:
|
||||
raise LookupError("User not found")
|
||||
|
||||
await self.db.delete(user)
|
||||
await self.db.commit()
|
||||
|
||||
async def get_email_in_address(self, user_id: UUID) -> dict:
|
||||
from cartsnitch_api.models import User
|
||||
|
||||
result = await self.db.execute(
|
||||
select(User.email_inbound_token).where(User.id == str(user_id))
|
||||
)
|
||||
token = result.scalar_one_or_none()
|
||||
if not token:
|
||||
raise LookupError("Email inbound token not found")
|
||||
|
||||
return {
|
||||
"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."
|
||||
),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user