Add logging to redeem process

This commit is contained in:
Ramon Wenger 2023-08-17 16:15:44 +02:00
parent 67ebcbcaa0
commit f71f7eff0f
3 changed files with 72 additions and 52 deletions

View File

@ -12,10 +12,11 @@ from core.logger import get_logger
logger = get_logger(__name__)
VALID_PRODUCT_STATES = ['waiting', 'paid', 'completed', 'shipped']
VALID_PRODUCT_STATES = ["waiting", "paid", "completed", "shipped"]
licenses = get_license_dict()
class HepClientException(Exception):
pass
@ -29,16 +30,16 @@ class HepClientNoTokenException(Exception):
class HepClient:
def _call(self, url, token_dict, method='get', data=None):
def _call(self, url, token_dict, method="get", data=None):
headers = {"accept": "application/json"}
if method == 'post':
if method == "post":
response = oauth.hep.post(url, json=data, token=token_dict, headers=headers)
elif method == 'get':
response = oauth.hep.get(url, params=data, token=token_dict, headers=headers)
elif method == 'put':
elif method == "get":
response = oauth.hep.get(
url, params=data, token=token_dict, headers=headers
)
elif method == "put":
response = oauth.hep.put(url, data=data, token=token_dict, headers=headers)
return self._handle_response(response)
@ -47,7 +48,9 @@ class HepClient:
if response.status_code == 401:
raise HepClientUnauthorizedException(response.status_code, response.json())
elif response.status_code != 200:
logger.warning(f'Hepclient error: Received {response.status_code} {response.json()}')
logger.warning(
f"Hepclient error: Received {response.status_code} {response.json()}"
)
raise HepClientException(response.status_code, response.json())
return response
@ -57,13 +60,15 @@ class HepClient:
raise HepClientNoTokenException
if not token_dict:
token_dict = fetch_token('', request)
token_dict = fetch_token("", request)
if not token_dict:
raise HepClientNoTokenException
if OAuth2Token.is_dict_expired(token_dict):
refresh_data = self._refresh_token(token_dict)
token, refresh_success = OAuth2Token.update_dict_with_refresh_data(refresh_data, token_dict['access_token'])
token, refresh_success = OAuth2Token.update_dict_with_refresh_data(
refresh_data, token_dict["access_token"]
)
if not refresh_success:
raise HepClientUnauthorizedException
@ -72,38 +77,40 @@ class HepClient:
return token_dict
def _refresh_token(self, token_dict):
data = {
'grant_type': 'refresh_token',
'refresh_token': token_dict['refresh_token'],
'client_id': settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_id'],
'client_secret': settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_secret'],
'scope': ''
}
"grant_type": "refresh_token",
"refresh_token": token_dict["refresh_token"],
"client_id": settings.AUTHLIB_OAUTH_CLIENTS["hep"]["client_id"],
"client_secret": settings.AUTHLIB_OAUTH_CLIENTS["hep"]["client_secret"],
"scope": "",
}
response = requests.post(f'{settings.AUTHLIB_OAUTH_CLIENTS["hep"]["api_base_url"]}/oauth/token', json=data)
response = requests.post(
f'{settings.AUTHLIB_OAUTH_CLIENTS["hep"]["api_base_url"]}/oauth/token',
json=data,
)
return self._handle_response(response).json()
def is_email_verified(self, user_data):
return user_data['email_verified_at'] is not None
return user_data["email_verified_at"] is not None
def user_details(self, request=None, token_dict=None):
token_dict = self._get_valid_token(request, token_dict)
response = self._call('api/auth/user', token_dict)
return response.json()['data']
response = self._call("api/auth/user", token_dict)
return response.json()["data"]
def logout(self, request=None, token_dict=None):
token_dict = self._get_valid_token(request, token_dict)
self._call('api/auth/logout', token_dict, method='post')
self._call("api/auth/logout", token_dict, method="post")
return True
def fetch_eorders(self, request=None, token_dict=None):
token_dict = self._get_valid_token(request, token_dict)
data = {
'filters[product_type]': 'eLehrmittel',
"filters[product_type]": "eLehrmittel",
}
response = self._call('api/partners/users/orders/search', token_dict, data=data)
return response.json()['data']
response = self._call("api/partners/users/orders/search", token_dict, data=data)
return response.json()["data"]
def active_myskillbox_product_for_customer(self, request=None, token_dict=None):
eorders = self.fetch_eorders(request=request, token_dict=token_dict)
@ -118,9 +125,14 @@ class HepClient:
def redeem_coupon(self, coupon_code, customer_id, request=None, token_dict=None):
token_dict = self._get_valid_token(request, token_dict)
try:
response = self._call(f'api/partners/users/{customer_id}/coupons/redeem', token_dict, method='post',
data={'code': coupon_code})
response = self._call(
f"api/partners/users/{customer_id}/coupons/redeem",
token_dict,
method="post",
data={"code": coupon_code},
)
except HepClientException:
logger.warning("could not redeem")
return None
response_data = response.json()
@ -130,14 +142,15 @@ class HepClient:
products = []
for eorder in eorders:
if 'items' not in eorder:
if "items" not in eorder:
continue
status = eorder.get('status', '')
status = eorder.get("status", "")
for entry in eorder['items']:
product = self.entry_to_product(entry, self._get_item_activation(eorder), status)
for entry in eorder["items"]:
product = self.entry_to_product(
entry, self._get_item_activation(eorder), status
)
if product:
products.append(product)
@ -145,35 +158,35 @@ class HepClient:
return products
def entry_to_product(self, entry, activation_date, status):
isbn = entry['isbn']
isbn = entry["isbn"]
if is_myskillbox_product(isbn) and activation_date:
return {
'raw': entry,
'activated': activation_date,
'status': status,
'order_id': entry['id'],
'license': licenses[isbn],
'isbn': entry['isbn']
}
"raw": entry,
"activated": activation_date,
"status": status,
"order_id": entry["id"],
"license": licenses[isbn],
"isbn": entry["isbn"],
}
return None
def _get_item_activation(self, eorder):
if 'created_at' in eorder:
return parse_datetime(eorder['created_at'])
if "created_at" in eorder:
return parse_datetime(eorder["created_at"])
else:
return None
def _get_active_product(self, products):
def filter_valid_products(product):
if product['status'] not in VALID_PRODUCT_STATES:
if product["status"] not in VALID_PRODUCT_STATES:
return False
expiry_delta = product['activated'] + timedelta(product['license']['duration'])
expiry_delta = product["activated"] + timedelta(
product["license"]["duration"]
)
return License.is_product_active(expiry_delta, product['isbn'])
return License.is_product_active(expiry_delta, product["isbn"])
active_products = list(filter(filter_valid_products, products))
@ -185,10 +198,9 @@ class HepClient:
return self._select_from_teacher_products(active_products)
def _select_from_teacher_products(self, active_products):
# select first teacher product, as they are all valid it does not matter which one
for product in active_products:
if product['license']['edition'] == TEACHER_KEY:
if product["license"]["edition"] == TEACHER_KEY:
return product
# select a student product, as they are all valid it does not matter which one

View File

@ -2,6 +2,7 @@ import graphene
from django.contrib.auth import logout
from django.utils.timezone import now
from graphene import relay
from core.logger import get_logger
from oauth.hep_client import HepClient, HepClientException
from oauth.models import OAuth2Token
@ -9,6 +10,8 @@ from oauth.types import InvalidCouponFailure, RedeemCouponResult, RedeemCouponSu
from oauth.user_signup_login_handler import create_role_for_user
from users.models import License
logger = get_logger(__name__)
class Coupon(relay.ClientIDMutation):
class Input:
@ -20,6 +23,7 @@ class Coupon(relay.ClientIDMutation):
def mutate_and_get_payload(cls, root, info, **kwargs):
coupon_code = kwargs.get("coupon_code").strip()
hep_client = HepClient()
logger.info("redeeming coupon")
try:
hep_id = info.context.user.hep_id
@ -31,7 +35,8 @@ class Coupon(relay.ClientIDMutation):
response = hep_client.redeem_coupon(
coupon_code, hep_id, request=info.context
)
except HepClientException:
except HepClientException as e:
logger.warning(e)
raise Exception("unknown_error")
if not response:
@ -40,8 +45,10 @@ class Coupon(relay.ClientIDMutation):
product = hep_client.entry_to_product(response["data"], now(), "coupon")
if not product:
logger.info("no myskillbox-product found")
raise Exception("non_myskillbox_product")
logger.info("creating license")
license = License.objects.create_license_for_role(
info.context.user,
product["activated"],
@ -51,6 +58,7 @@ class Coupon(relay.ClientIDMutation):
product["isbn"],
)
logger.info("creating role for user")
create_role_for_user(info.context.user, license.for_role.key)
return cls(result=RedeemCouponSuccess)

View File

@ -30,7 +30,7 @@ def handle_user_and_verify_products(user_data, token):
license, error_msg = check_and_create_licenses(hep_client, user, token)
if error_msg:
logger.warn(error_msg)
logger.warning(error_msg)
return user, error_msg
logger.info("creating role")