"""
Support Request API
Handles user support requests with page screenshots.
"""
import base64
import logging
from datetime import datetime
from fastapi import APIRouter, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession
from database import get_db
from auth import get_current_user, require_cap
from models.user import User, Kitchen
from models.settings import KitchenSettings
from services.email_service import EmailService
from sqlalchemy import select
router = APIRouter()
logger = logging.getLogger(__name__)
class SupportRequest(BaseModel):
"""Support request payload"""
description: str
screenshot: str # Base64 encoded PNG
page_url: str
browser_info: str | None = None
class SupportResponse(BaseModel):
"""Support request response"""
success: bool
message: str
def generate_support_email_html(
user_name: str,
user_email: str,
kitchen_name: str,
description: str,
page_url: str,
browser_info: str | None,
timestamp: datetime
) -> str:
"""Generate HTML email body for support request"""
return f"""
Issue Description
{description.replace(chr(10), '
')}
A screenshot of the page is attached to this email.
"""
@router.post("/support/request", response_model=SupportResponse)
async def submit_support_request(
request: SupportRequest,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""
Submit a support request with page screenshot.
The screenshot is sent as an email attachment to the configured support email.
"""
# Get kitchen settings
result = await db.execute(
select(KitchenSettings).where(KitchenSettings.kitchen_id == current_user.kitchen_id)
)
settings = result.scalar_one_or_none()
if not settings:
raise HTTPException(status_code=404, detail="Kitchen settings not found")
# Check if support email is configured
if not settings.support_email:
raise HTTPException(
status_code=400,
detail="Support email not configured. Please contact your administrator."
)
# Check if SMTP is configured
if not settings.smtp_host or not settings.smtp_from_email:
raise HTTPException(
status_code=400,
detail="Email settings not configured. Please contact your administrator."
)
# Fetch kitchen name explicitly to avoid lazy loading issues
kitchen_result = await db.execute(
select(Kitchen).where(Kitchen.id == current_user.kitchen_id)
)
kitchen = kitchen_result.scalar_one_or_none()
kitchen_name = kitchen.name if kitchen else "Unknown Kitchen"
try:
# Decode screenshot from base64
# Remove data URL prefix if present
screenshot_data = request.screenshot
if screenshot_data.startswith('data:'):
screenshot_data = screenshot_data.split(',', 1)[1]
screenshot_bytes = base64.b64decode(screenshot_data)
# Generate email
timestamp = datetime.utcnow()
html_body = generate_support_email_html(
user_name=current_user.name,
user_email=current_user.email,
kitchen_name=kitchen_name,
description=request.description,
page_url=request.page_url,
browser_info=request.browser_info,
timestamp=timestamp
)
# Create email subject
subject = f"Support Request from {current_user.name} - {kitchen_name}"
# Send email with screenshot attachment
email_service = EmailService(settings)
filename = f"screenshot_{timestamp.strftime('%Y%m%d_%H%M%S')}.png"
success = email_service.send_email(
to_email=settings.support_email,
subject=subject,
html_body=html_body,
attachments=[(filename, screenshot_bytes)]
)
if success:
logger.info(f"Support request sent from {current_user.name} to {settings.support_email}")
return SupportResponse(
success=True,
message="Support request sent successfully. We'll get back to you soon."
)
else:
logger.error(f"Failed to send support request email")
raise HTTPException(
status_code=500,
detail="Failed to send support request. Please try again later."
)
except base64.binascii.Error:
raise HTTPException(status_code=400, detail="Invalid screenshot data")
except Exception as e:
logger.error(f"Support request error: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/support/enabled")
async def check_support_enabled(
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db)
):
"""
Check if support requests are enabled (support email configured).
Returns whether the support button should be shown.
"""
result = await db.execute(
select(KitchenSettings).where(KitchenSettings.kitchen_id == current_user.kitchen_id)
)
settings = result.scalar_one_or_none()
enabled = bool(
settings and
settings.support_email and
settings.smtp_host and
settings.smtp_from_email
)
return {"enabled": enabled}