Implement real Wix token-backed routes and error mapping

This commit is contained in:
ي
2026-05-11 15:50:25 +05:30
committed by ajaysi
parent 9afd0d322d
commit 68190dedb3

View File

@@ -17,6 +17,7 @@ from middleware.auth_middleware import get_current_user
import os
import json
from urllib.parse import urlparse
import requests
router = APIRouter(prefix="/api/wix", tags=["Wix Integration"])
qa_router = APIRouter(prefix="/api/wix/test", tags=["Wix Integration QA"])
@@ -86,6 +87,63 @@ wix_service = WixService()
wix_oauth_service = WixOAuthService()
def _get_current_user_id(current_user: dict) -> str:
user_id = current_user.get("id") if current_user else None
if not user_id:
raise HTTPException(status_code=401, detail="Missing authenticated user context")
return user_id
def _map_wix_error(exc: Exception, fallback: str = "Wix API request failed") -> HTTPException:
if isinstance(exc, HTTPException):
return exc
if isinstance(exc, requests.HTTPError):
status = exc.response.status_code if exc.response is not None else None
if status == 401:
return HTTPException(status_code=401, detail="Wix authentication expired or invalid")
if status == 403:
return HTTPException(status_code=403, detail="Insufficient Wix permissions/scope")
return HTTPException(status_code=502, detail=fallback)
if isinstance(exc, requests.RequestException):
return HTTPException(status_code=502, detail=fallback)
return HTTPException(status_code=500, detail=str(exc))
def _resolve_valid_wix_token(current_user: dict) -> Dict[str, Any]:
user_id = _get_current_user_id(current_user)
tokens = wix_oauth_service.get_user_tokens(user_id)
if tokens:
return tokens[0]
token_status = wix_oauth_service.get_user_token_status(user_id)
expired_tokens = token_status.get("expired_tokens", [])
if not expired_tokens:
raise HTTPException(status_code=401, detail="Wix account not connected")
latest = expired_tokens[0]
refresh_token = latest.get("refresh_token")
if not refresh_token:
raise HTTPException(status_code=401, detail="Wix token expired and cannot be refreshed")
try:
refreshed = wix_service.refresh_access_token(refresh_token)
except Exception as exc:
raise _map_wix_error(exc, "Failed to refresh Wix access token")
wix_oauth_service.update_tokens(
user_id=user_id,
access_token=refreshed.get("access_token"),
refresh_token=refreshed.get("refresh_token", refresh_token),
expires_in=refreshed.get("expires_in"),
)
return {
"access_token": refreshed.get("access_token"),
"refresh_token": refreshed.get("refresh_token", refresh_token),
"member_id": latest.get("member_id"),
"site_id": latest.get("site_id"),
}
class WixAuthRequest(BaseModel):
"""Request model for Wix authentication"""
code: str
@@ -351,21 +409,20 @@ async def get_connection_status(current_user: dict = Depends(get_current_user))
Connection status and permissions
"""
try:
# Check if user has Wix tokens stored in sessionStorage (frontend approach)
# This is a simplified check - in production you'd store tokens in database
token_info = _resolve_valid_wix_token(current_user)
access_token = token_info["access_token"]
site_info = wix_service.get_site_info(access_token)
permissions = wix_service.check_blog_permissions(access_token)
return WixConnectionStatus(
connected=False,
has_permissions=False,
error="No Wix connection found. Please connect your Wix account first."
connected=True,
has_permissions=permissions.get("has_permissions", False),
site_info=site_info,
permissions=permissions
)
except Exception as e:
logger.error(f"Failed to check connection status: {e}")
return WixConnectionStatus(
connected=False,
has_permissions=False,
error=str(e)
)
mapped = _map_wix_error(e, "Failed to check Wix connection status")
raise mapped
@router.get("/status")
@@ -376,22 +433,18 @@ async def get_wix_status(current_user: dict = Depends(get_current_user)) -> Dict
The frontend will check sessionStorage and update the UI accordingly.
"""
try:
# Since Wix tokens are stored in frontend sessionStorage (not backend database),
# we return a default response. The frontend will check sessionStorage directly.
token_info = _resolve_valid_wix_token(current_user)
site_info = wix_service.get_site_info(token_info["access_token"])
return {
"connected": False,
"sites": [],
"total_sites": 0,
"error": "Wix connection status managed by frontend sessionStorage"
"connected": True,
"sites": [site_info],
"total_sites": 1,
"site_info": site_info
}
except Exception as e:
logger.error(f"Failed to get Wix status: {e}")
return {
"connected": False,
"sites": [],
"total_sites": 0,
"error": str(e)
}
mapped = _map_wix_error(e, "Failed to get Wix status")
raise mapped
@router.post("/publish")
@@ -407,63 +460,36 @@ async def publish_to_wix(request: WixPublishRequest, current_user: dict = Depend
Published blog post information
"""
try:
# TODO: Retrieve stored access token from database for current_user
# For now, we'll return an error asking user to connect first
token_info = _resolve_valid_wix_token(current_user)
access_token = token_info["access_token"]
member_id = token_info.get("member_id") or wix_service.extract_member_id_from_access_token(access_token)
if not member_id:
member_info = wix_service.get_current_member(access_token)
member_id = (member_info.get("member") or {}).get("id") or member_info.get("id")
if not member_id:
raise HTTPException(status_code=401, detail="Unable to resolve Wix member ID")
result = wix_service.create_blog_post(
access_token=access_token,
title=request.title,
content=request.content,
cover_image_url=request.cover_image_url,
category_ids=request.category_ids,
tag_ids=request.tag_ids,
publish=request.publish,
member_id=member_id,
)
post = result.get("draftPost") or result.get("post") or result
return {
"success": False,
"error": "Wix account not connected. Please connect your Wix account first.",
"message": "Use the /api/wix/auth/url endpoint to get the authorization URL"
"success": True,
"post_id": post.get("id"),
"url": post.get("url"),
"publish_state": "PUBLISHED" if request.publish else "DRAFT"
}
# Example of what the actual implementation would look like:
# access_token = get_stored_access_token(current_user['id'])
#
# if not access_token:
# raise HTTPException(status_code=401, detail="Wix account not connected")
#
# # Check if token is still valid, refresh if needed
# try:
# site_info = wix_service.get_site_info(access_token)
# except:
# # Token expired, try to refresh
# refresh_token = get_stored_refresh_token(current_user['id'])
# if refresh_token:
# new_tokens = wix_service.refresh_access_token(refresh_token)
# access_token = new_tokens['access_token']
# # Store new tokens
# else:
# raise HTTPException(status_code=401, detail="Wix session expired. Please reconnect.")
#
# # Get current member ID (required for third-party apps)
# member_info = wix_service.get_current_member(access_token)
# member_id = member_info.get('member', {}).get('id')
#
# if not member_id:
# raise HTTPException(status_code=400, detail="Could not retrieve member ID")
#
# # Create blog post
# result = wix_service.create_blog_post(
# access_token=access_token,
# title=request.title,
# content=request.content,
# cover_image_url=request.cover_image_url,
# category_ids=request.category_ids,
# tag_ids=request.tag_ids,
# publish=request.publish,
# member_id=member_id # Required for third-party apps
# )
#
# return {
# "success": True,
# "post_id": result.get('draftPost', {}).get('id'),
# "url": result.get('draftPost', {}).get('url'),
# "message": "Blog post published successfully to Wix"
# }
except Exception as e:
logger.error(f"Failed to publish to Wix: {e}")
raise HTTPException(status_code=500, detail=str(e))
raise _map_wix_error(e, "Failed to publish to Wix")
@router.get("/categories")
@@ -478,23 +504,15 @@ async def get_blog_categories(current_user: dict = Depends(get_current_user)) ->
List of blog categories
"""
try:
# TODO: Retrieve stored access token from database for current_user
token_info = _resolve_valid_wix_token(current_user)
categories = wix_service.get_blog_categories(token_info["access_token"])
return {
"success": False,
"error": "Wix account not connected. Please connect your Wix account first."
"success": True,
"categories": categories
}
# Example implementation:
# access_token = get_stored_access_token(current_user['id'])
# if not access_token:
# raise HTTPException(status_code=401, detail="Wix account not connected")
#
# categories = wix_service.get_blog_categories(access_token)
# return {"categories": categories}
except Exception as e:
logger.error(f"Failed to get blog categories: {e}")
raise HTTPException(status_code=500, detail=str(e))
raise _map_wix_error(e, "Failed to fetch Wix blog categories")
@router.get("/tags")
@@ -509,23 +527,15 @@ async def get_blog_tags(current_user: dict = Depends(get_current_user)) -> Dict[
List of blog tags
"""
try:
# TODO: Retrieve stored access token from database for current_user
token_info = _resolve_valid_wix_token(current_user)
tags = wix_service.get_blog_tags(token_info["access_token"])
return {
"success": False,
"error": "Wix account not connected. Please connect your Wix account first."
"success": True,
"tags": tags
}
# Example implementation:
# access_token = get_stored_access_token(current_user['id'])
# if not access_token:
# raise HTTPException(status_code=401, detail="Wix account not connected")
#
# tags = wix_service.get_blog_tags(access_token)
# return {"tags": tags}
except Exception as e:
logger.error(f"Failed to get blog tags: {e}")
raise HTTPException(status_code=500, detail=str(e))
raise _map_wix_error(e, "Failed to fetch Wix blog tags")
@router.post("/disconnect")
@@ -540,15 +550,22 @@ async def disconnect_wix(current_user: dict = Depends(get_current_user)) -> Dict
Disconnection status
"""
try:
# TODO: Remove stored tokens from database for current_user
user_id = _get_current_user_id(current_user)
token_status = wix_oauth_service.get_user_token_status(user_id)
all_tokens = token_status.get("active_tokens", []) + token_status.get("expired_tokens", [])
for token in all_tokens:
token_id = token.get("id")
if token_id:
wix_oauth_service.revoke_token(user_id, token_id)
return {
"success": True,
"connected": False,
"message": "Wix account disconnected successfully"
}
except Exception as e:
logger.error(f"Failed to disconnect Wix: {e}")
raise HTTPException(status_code=500, detail=str(e))
raise _map_wix_error(e, "Failed to disconnect Wix account")
# =============================================================================