from __future__ import annotations import logging from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.requests import AuthRequest from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from ows_text_campaigns.adapters.db.decorators import transactional from ows_text_campaigns.assets.image import ImageProcessor from ows_text_campaigns.assets.models import Asset from ows_text_campaigns.assets.services import AssetService from ows_text_campaigns.campaigns.exceptions import InvalidCampaignAttachmentError from ows_text_campaigns.campaigns.services import CampaignService from ows_text_campaigns.config import Settings logger = logging.getLogger(__name__) @dataclass(kw_only=True) class CreateCampaignAttachmentRequest(AuthRequest): campaign_id: str attachment_key: str @singleton class CreateCampaignAttachmentHandler: permission = Permission("text_campaign", "edit") def __init__( self, auth_service: AuthService, asset_service: AssetService, campaign_service: CampaignService, image_processor: ImageProcessor, settings: Settings, ) -> None: self.auth_service = auth_service self.asset_service = asset_service self.campaign_service = campaign_service self.image_processor = image_processor self.settings = settings @transactional def handle(self, request: CreateCampaignAttachmentRequest) -> Asset: campaign = self.campaign_service.get_campaign(request.campaign_id) self.auth_service.check_account_resource( request.identity_id, account=campaign.account, permission=self.permission, resource_id=campaign.id, ) try: asset = self.asset_service.get_asset_from_s3(request.attachment_key) except Exception as exc: logger.exception( "Failed to get campaign `%s` attachment", request.campaign_id, extra={ "attachment_key": request.attachment_key, "campaign_id": request.campaign_id, }, ) raise InvalidCampaignAttachmentError from exc # Validate image image = self.image_processor.validate_and_process( asset, max_file_size=self.settings.campaign_attachment_max_file_size, min_width=self.settings.campaign_attachment_min_width, min_height=self.settings.campaign_attachment_min_height, allowed_content_types=self.settings.campaign_attachment_allowed_content_types, ) return self.asset_service.create_and_upload_image_to_s3( image, request.attachment_key, object_type="text_campaign", object_id=campaign.id, identity_id=request.identity_id, )