def authenticate_facebook( self, session: Session, facebook_user_id: str, access_token: str, email: str, first_name: str, last_name: str, role: UserRole, authenticated_user: User = None, ): user: User = None # TODO refactor social account methods into service? existing_facebook_social_account: Optional[SocialAccount] = ( session.query(SocialAccount).filter( SocialAccount.account_type == SocialAccountType.FACEBOOK). filter(SocialAccount.account_id == facebook_user_id).one_or_none()) if not authenticated_user and existing_facebook_social_account: # social account exists therefore user exists # sing in with facebook user: User = existing_facebook_social_account.user existing_facebook_social_account.access_token = access_token existing_facebook_social_account.account_email = email elif not authenticated_user: # sign up with facebook user_with_email = self.user_service.get_by_email(session, email) if user_with_email: raise ApplicationError("User exists with this email address") user = self.user_service.create( session, first_name=first_name, last_name=last_name, email=email, email_verified=True, role=role, commit=False, ) session.flush() existing_facebook_social_account = SocialAccount( user_id=user.id, access_token=access_token, account_id=facebook_user_id, account_email=email, account_type=SocialAccountType.FACEBOOK, ) session.add(existing_facebook_social_account) elif not existing_facebook_social_account: # link facebook account # does user already havea an existing facebook account authenticated_users_existing_facebook_account = ( session.query(SocialAccount).filter( SocialAccount.user_id == authenticated_user.id).filter( SocialAccount.account_type == SocialAccountType.FACEBOOK).one_or_none()) if authenticated_users_existing_facebook_account: # update the account if yes authenticated_users_existing_facebook_account.access_token = ( access_token) authenticated_users_existing_facebook_account.account_email = email authenticated_users_existing_facebook_account.account_id = ( facebook_user_id) else: # create a new one if not. existing_facebook_social_account = SocialAccount( user_id=authenticated_user.id, access_token=access_token, account_id=facebook_user_id, account_email=email, account_type=SocialAccountType.FACEBOOK, ) session.add(existing_facebook_social_account) user = authenticated_user else: # update facebook account user: User = existing_facebook_social_account.user if authenticated_user != user: raise ApplicationError( "Facebook Account is linked to another user") existing_facebook_social_account.access_token = access_token existing_facebook_social_account.account_email = email session.commit() return util.create_access_token(data={"sub": str(user.id)})