feat: add share calendar API
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
import json
|
||||
from typing import TYPE_CHECKING, Protocol
|
||||
from uuid import UUID
|
||||
|
||||
from fastapi import HTTPException
|
||||
@@ -9,13 +10,17 @@ from sqlalchemy.exc import SQLAlchemyError
|
||||
from core.auth.models import CurrentUser
|
||||
from core.db.base_service import BaseService
|
||||
from core.logging import get_logger
|
||||
from models.inbox_messages import InboxMessage, InboxMessageType
|
||||
from models.schedule_items import ScheduleItem
|
||||
from v1.auth.gateway import SupabaseAuthGateway
|
||||
from v1.schedule_items.repository import ScheduleItemRepository
|
||||
from v1.schedule_items.schemas import (
|
||||
ScheduleItemCreateRequest,
|
||||
ScheduleItemListRequest,
|
||||
ScheduleItemMetadata,
|
||||
ScheduleItemResponse,
|
||||
ScheduleItemShareRequest,
|
||||
ScheduleItemShareResponse,
|
||||
ScheduleItemUpdateRequest,
|
||||
ScheduleItemSourceType,
|
||||
ScheduleItemStatus,
|
||||
@@ -24,22 +29,31 @@ from v1.schedule_items.schemas import (
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from v1.auth.schemas import UserByEmailResponse
|
||||
|
||||
logger = get_logger("v1.schedule_items.service")
|
||||
|
||||
|
||||
class AuthByEmailGateway(Protocol):
|
||||
async def get_user_by_email(self, email: str) -> "UserByEmailResponse": ...
|
||||
|
||||
|
||||
class ScheduleItemService(BaseService):
|
||||
_repository: ScheduleItemRepository
|
||||
_session: AsyncSession
|
||||
_auth_gateway: AuthByEmailGateway
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
repository: ScheduleItemRepository,
|
||||
session: AsyncSession,
|
||||
current_user: CurrentUser | None,
|
||||
auth_gateway: AuthByEmailGateway | None = None,
|
||||
) -> None:
|
||||
super().__init__(current_user=current_user)
|
||||
self._repository = repository
|
||||
self._session = session
|
||||
self._auth_gateway = auth_gateway or SupabaseAuthGateway()
|
||||
|
||||
async def create(self, request: ScheduleItemCreateRequest) -> ScheduleItemResponse:
|
||||
user_id = self.require_user_id()
|
||||
@@ -179,6 +193,50 @@ class ScheduleItemService(BaseService):
|
||||
|
||||
return [self._to_response(item) for item in items]
|
||||
|
||||
async def share(
|
||||
self, item_id: UUID, request: ScheduleItemShareRequest
|
||||
) -> ScheduleItemShareResponse:
|
||||
user_id = self.require_user_id()
|
||||
|
||||
try:
|
||||
item = await self._repository.get_by_id(item_id)
|
||||
if item is None:
|
||||
raise HTTPException(status_code=404, detail="Schedule item not found")
|
||||
if item.owner_id != user_id:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail="Only owner can share this schedule item",
|
||||
)
|
||||
|
||||
target_user = await self._auth_gateway.get_user_by_email(request.email)
|
||||
recipient_id = UUID(target_user.id)
|
||||
message = InboxMessage(
|
||||
recipient_id=recipient_id,
|
||||
sender_id=user_id,
|
||||
message_type=InboxMessageType.CALENDAR,
|
||||
schedule_item_id=item.id,
|
||||
content=json.dumps({"permission": request._permission_value()}),
|
||||
created_by=user_id,
|
||||
)
|
||||
self._session.add(message)
|
||||
await self._session.commit()
|
||||
except HTTPException:
|
||||
raise
|
||||
except SQLAlchemyError:
|
||||
await self._session.rollback()
|
||||
logger.exception("Failed to share schedule item", item_id=str(item_id))
|
||||
raise HTTPException(
|
||||
status_code=503, detail="Schedule item store unavailable"
|
||||
)
|
||||
except ValueError:
|
||||
await self._session.rollback()
|
||||
logger.exception(
|
||||
"Auth lookup returned invalid user id", email=request.email
|
||||
)
|
||||
raise HTTPException(status_code=503, detail="Auth lookup unavailable")
|
||||
|
||||
return ScheduleItemShareResponse(message="Calendar invitation sent")
|
||||
|
||||
def _to_response(self, item: ScheduleItem) -> ScheduleItemResponse:
|
||||
return ScheduleItemResponse(
|
||||
id=item.id,
|
||||
|
||||
Reference in New Issue
Block a user