Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions src/backend/database/service/pad_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@
Pad service for business logic related to pads.
"""

from typing import List, Optional, Dict, Any
from typing import List, Optional, Dict, Any, TYPE_CHECKING
from uuid import UUID

from sqlalchemy.ext.asyncio import AsyncSession

from ..repository import PadRepository, UserRepository
from .user_service import UserService

# Use TYPE_CHECKING to avoid circular imports
if TYPE_CHECKING:
from dependencies import UserSession

class PadService:
"""Service for pad-related business logic"""

Expand All @@ -19,7 +23,7 @@ def __init__(self, session: AsyncSession):
self.repository = PadRepository(session)
self.user_repository = UserRepository(session)

async def create_pad(self, owner_id: UUID, display_name: str, data: Dict[str, Any], token_data: Dict[str, Any]) -> Dict[str, Any]:
async def create_pad(self, owner_id: UUID, display_name: str, data: Dict[str, Any], user_session: "UserSession" = None) -> Dict[str, Any]:
"""Create a new pad"""
# Validate input
if not display_name:
Expand All @@ -28,20 +32,37 @@ async def create_pad(self, owner_id: UUID, display_name: str, data: Dict[str, An
if not data:
raise ValueError("Pad data is required")

if not token_data:
raise ValueError("Token data is required for user creation failsafe")

# Check if owner exists
owner = await self.user_repository.get_by_id(owner_id)
if not owner:
# User doesn't exist, create a user record from token data
print(f"WARNING: User with ID '{owner_id}' does not exist but is trying to save a pad. Creating user as failsafe.")
if not owner and user_session:
# User doesn't exist, create a user record from user session
print(f"ANOMALY DETECTED: User with ID '{owner_id}' does not exist but has valid authentication. Creating user as failsafe.")

# Create a UserService instance
user_service = UserService(self.session)

# Use token data to create a complete user record
await user_service.sync_user_with_token_data(owner_id, token_data)
# Create user with data from UserSession
try:
await user_service.create_user(
user_id=user_session.id,
username=user_session.username,
email=user_session.email,
email_verified=user_session.email_verified,
name=user_session.name,
given_name=user_session.given_name,
family_name=user_session.family_name,
roles=user_session.roles
)
print(f"Successfully created user with ID '{owner_id}' as failsafe.")
except ValueError as e:
print(f"Error creating user as failsafe: {str(e)}")
# If user creation fails due to race condition, try to get the user again
if "already exists" in str(e):
owner = await self.user_repository.get_by_id(owner_id)
if not owner:
raise ValueError(f"Failed to create user with ID '{owner_id}'")
else:
raise

# Check if pad with same name already exists for this owner
existing_pad = await self.repository.get_by_name(owner_id, display_name)
Expand Down
4 changes: 2 additions & 2 deletions src/backend/routers/pad_router.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async def save_pad(
owner_id=user.id,
display_name=DEFAULT_PAD_NAME,
data=data,
token_data=user.token_data
user_session=user
)
else:
# Update existing pad
Expand Down Expand Up @@ -101,7 +101,7 @@ async def create_pad_from_template(
owner_id=user.id,
display_name=display_name,
data=template["data"],
token_data=user.token_data
user_session=user
)

# Create an initial backup for the new pad
Expand Down