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 dmp.adapters.db import DefaultDB, transactional from dmp.adapters.google import GoogleClient from dmp.core.types import PlainToken from dmp.google.dtos import GoogleUser, GoogleUserConnectionResponse from dmp.google.models import GoogleUserConnection from dmp.google.repositories import GoogleUserConnectionRepository from dmp.google.services import GoogleAdAccountService, GoogleUserConnectionService @dataclass class ConnectGoogleUserRequest(AuthRequest): auth_code: PlainToken redirect_uri: str code_verifier: str @singleton class ConnectGoogleUserHandler: permission = Permission("ad_connection", "connect") def __init__( self, db: DefaultDB, auth_service: AuthService, user_connection_service: GoogleUserConnectionService, user_connection_repository: GoogleUserConnectionRepository, ad_account_service: GoogleAdAccountService, google_client: GoogleClient, ) -> None: self.db = db self.auth_service = auth_service self.user_connection_service = user_connection_service self.user_connection_repository = user_connection_repository self.ad_account_service = ad_account_service self.google_client = google_client @transactional def handle(self, request: ConnectGoogleUserRequest) -> GoogleUserConnectionResponse: self.auth_service.check_owned_resource( request.identity_id, permission=self.permission, ) token_response = self.user_connection_service.get_refresh_token( auth_code=request.auth_code, redirect_uri=request.redirect_uri, code_verifier=request.code_verifier, ) user = self.google_client.get_user(token_response.access_token) encrypted_token = self.user_connection_service.encrypt_token( token_response.refresh_token ) user_connection = self.user_connection_service.create_or_update_user_connection( GoogleUserConnection( identity_id=request.identity_id, user_id=user.id, user_name=user.name, token=encrypted_token, ) ) api_ad_accounts = self.ad_account_service.get_api_ad_accounts_for_connection( access_token=token_response.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) return self.user_connection_service.make_connected_response( user_connection, user=GoogleUser( id=user.id, name=user.name, granted_scopes=token_response.scope_list ), )