from dataclasses import dataclass from anydi import singleton from fansifter_common.auth.services import AuthService from fansifter_common.auth.types import Permission from dmp.adapters.db import DefaultDB, transactional from dmp.adapters.google import GoogleClientError from dmp.config import Settings from dmp.google.dtos import GoogleUser, GoogleUserConnectionResponse from dmp.google.enums import GoogleUserConnectionStatus from dmp.google.services import GoogleAdAccountService, GoogleUserConnectionService @dataclass(frozen=True) class GetGoogleUserConnectionRequest: identity_id: str user_id: str @singleton class GetGoogleUserConnectionHandler: permission = Permission("ad_connection", "view") def __init__( self, db: DefaultDB, auth_service: AuthService, user_connection_service: GoogleUserConnectionService, ad_account_service: GoogleAdAccountService, settings: Settings, ) -> None: self.db = db self.auth_service = auth_service self.user_connection_service = user_connection_service self.ad_account_service = ad_account_service self.settings = settings @transactional def handle( self, request: GetGoogleUserConnectionRequest ) -> GoogleUserConnectionResponse: user_connection = self.user_connection_service.get_user_connection( identity_id=request.identity_id, user_id=request.user_id, ) if not user_connection: return self.user_connection_service.make_error_response( status=GoogleUserConnectionStatus.NOT_CONNECTED, ) self.auth_service.check_owned_resource( user_connection.identity_id, permission=self.permission, resource_id=user_connection.id, ) if not user_connection.is_valid: return self.user_connection_service.make_error_response( status=GoogleUserConnectionStatus.INVALID, ) refresh_token = self.user_connection_service.decrypt_token( user_connection.token ) try: token = self.user_connection_service.get_access_token( refresh_token=refresh_token ) if not token.scopes_sufficient(self.settings.google_user_required_scopes): return self.user_connection_service.make_error_response( status=GoogleUserConnectionStatus.SCOPES_MISSING, ) user = self.user_connection_service.get_user( access_token=token.access_token, ) self.user_connection_service.update_user_data(user_connection, user) api_ad_accounts = ( self.ad_account_service.get_api_ad_accounts_for_connection( access_token=token.access_token ) ) ad_accounts = self.ad_account_service.get_ad_accounts_for_user_connection( connection=user_connection, external_ad_accounts=api_ad_accounts, ) user_connection.add_ad_accounts(ad_accounts, api_ad_accounts) self.user_connection_service.save_user_connection(user_connection) except GoogleClientError: user_connection.is_valid = False self.user_connection_service.save_user_connection(user_connection) return self.user_connection_service.make_error_response( status=GoogleUserConnectionStatus.INVALID, ) self.user_connection_service.save_user_connection(user_connection) return self.user_connection_service.make_connected_response( user_connection, user=GoogleUser( id=user.id, name=user.name, granted_scopes=token.scope_list, ), )