from dataclasses import dataclass from campaigns.connectors.aws.kms import BaseKMS from campaigns.connectors.db import Database, session_context from campaigns.connectors.facebook.base import FacebookClient from campaigns.core.handler import Handler from campaigns.meta import constants from campaigns.meta.dtos import FacebookConnection, FacebookUser from campaigns.meta.enums import FacebookConnectionStatus from campaigns.meta.repositories import FacebookAssociationRepository @dataclass(frozen=True) class GetFacebookConnectionStatusRequest: identity_id: str @dataclass class GetFacebookConnectionStatusHandler( Handler[GetFacebookConnectionStatusRequest, FacebookConnection], ): db: Database kms: BaseKMS facebook_client: FacebookClient facebook_association_repository: FacebookAssociationRepository @session_context(in_transaction=False) async def handle( self, request: GetFacebookConnectionStatusRequest ) -> FacebookConnection: association = ( await self.facebook_association_repository.get_by_identity_id_or_none( identity_id=request.identity_id ) ) if not association: return FacebookConnection.not_connected() required_scopes = constants.REQUIRED_SCOPES if not association or (association and not association.is_connected): return FacebookConnection.not_connected() if association.is_expired: return FacebookConnection( user=FacebookUser(id=association.user_id, name=association.user_name), status=FacebookConnectionStatus.INVALID, ) access_token = await self.kms.decrypt( association.token, context={"field": "token"} ) debug_token = await self.facebook_client.debug_token(access_token) if not debug_token.is_valid: return FacebookConnection( user=FacebookUser(id=association.user_id, name=association.user_name), status=FacebookConnectionStatus.INVALID, ) api_user = await self.facebook_client.get_user( user_id=association.user_id, user_access_token=access_token, ) user = FacebookUser.from_api_obj(api_user) user.granted_scopes = debug_token.scopes if not user.has_pages_scope(): return FacebookConnection( user=user, status=FacebookConnectionStatus.NO_PAGES ) if not user.scopes_sufficient(scopes=required_scopes): return FacebookConnection( user=user, status=FacebookConnectionStatus.SCOPES_MISSING, ) return FacebookConnection( user=user, status=FacebookConnectionStatus.CONNECTED, )