Files
edx-platform/scripts/user_retirement/utils/thirdparty_apis/braze_api.py
Muhammad Farhan Khan 65ea55c8aa Move user retirement scripts code from the tubular repo (#34063)
* refactor: Migragte user retirement scripts code from the tubular repo
2024-02-22 11:09:00 -05:00

86 lines
2.5 KiB
Python

"""
Helper API classes for calling Braze APIs.
"""
import logging
import os
import backoff
import requests
LOG = logging.getLogger(__name__)
MAX_ATTEMPTS = int(os.environ.get('RETRY_BRAZE_MAX_ATTEMPTS', 5))
class BrazeException(Exception):
pass
class BrazeRecoverableException(BrazeException):
pass
class BrazeApi:
"""
Braze API client used to make calls to Braze
"""
def __init__(self, braze_api_key, braze_instance):
self.api_key = braze_api_key
# https://www.braze.com/docs/api/basics/#endpoints
self.base_url = 'https://rest.{instance}.braze.com'.format(instance=braze_instance)
def auth_headers(self):
"""Returns authorization headers suitable for passing to the requests library"""
return {
'Authorization': 'Bearer ' + self.api_key,
}
@staticmethod
def get_error_message(response):
"""Returns a string suitable for logging"""
try:
json = response.json()
except ValueError:
json = {}
# https://www.braze.com/docs/api/errors
message = json.get('message')
return message or response.reason
def process_response(self, response, action):
"""Log response status and raise an error as needed"""
if response.ok:
LOG.info('Braze {action} succeeded'.format(action=action))
return
# We have some sort of error. Parse it, log it, and retry as needed.
error_msg = 'Braze {action} failed due to {msg}'.format(action=action, msg=self.get_error_message(response))
LOG.error(error_msg)
if response.status_code == 429 or 500 <= response.status_code < 600:
raise BrazeRecoverableException(error_msg)
else:
raise BrazeException(error_msg)
@backoff.on_exception(
backoff.expo,
BrazeRecoverableException,
max_tries=MAX_ATTEMPTS,
)
def delete_user(self, learner):
"""
Delete a learner from Braze.
"""
# https://www.braze.com/docs/help/gdpr_compliance/#the-right-to-erasure
# https://www.braze.com/docs/api/endpoints/user_data/post_user_delete
response = requests.post(
self.base_url + '/users/delete',
headers=self.auth_headers(),
json={
'external_ids': [learner['user']['id']], # Braze external ids are LMS user ids
},
)
self.process_response(response, 'user deletion')