skillbox/server/oauth/hep_client.py

211 lines
7.0 KiB
Python

from django.utils.dateparse import parse_datetime
from datetime import timedelta
from django.conf import settings
import logging
import requests
from oauth.oauth_client import oauth
from users.licenses import MYSKILLBOX_LICENSES, is_myskillbox_product, TEACHER_KEY
from users.models import License
logger = logging.getLogger(__name__)
class HepClientException(Exception):
pass
class HepClientUnauthorizedException(Exception):
pass
class HepClientNoTokenException(Exception):
pass
class HepClient:
def _call(self, url, request, token, method='get', data=None):
token_parameters = {
'token': token,
'request': request
}
if method == 'post':
response = oauth.hep.post(url, json=data, **token_parameters)
elif method == 'get':
response = oauth.hep.get(url, params=data, **token_parameters)
elif method == 'put':
response = oauth.hep.put(url, data=data, **token_parameters)
if response.status_code == 401:
raise HepClientUnauthorizedException(response.status_code, response.json())
elif response.status_code != 200:
raise HepClientException(response.status_code, response.json())
return response
def is_email_verified(self, user_data):
return user_data['email_verified_at'] is not None
def user_details(self, request=None, token=None):
self._has_credentials(request, token)
response = self._call('api/auth/user', request, token)
return response.json()['data']
def logout(self, request=None, token=None):
self._has_credentials(request, token)
self._call('api/auth/logout', request, token, method='post')
return True
def fetch_eorders(self, request=None, token=None):
self._has_credentials(request, token)
data = {
'filters[product_type]': 'eLehrmittel',
}
response = self._call('api/partners/users/orders/search', request, token, data=data)
return response.json()['data']
# return [
# {
# "id": 5,
# "status": "paid",
# "order_total": 10000,
# "created_at": "2021-05-10T20:52:16.000000Z",
# "billing_address": {
# "id": 20,
# "salutation": "male",
# "first_name": "Hans",
# "last_name": "Meier",
# "company": "Lustig GmbH",
# "street": "Sulgenrain 12890",
# "city": "Bern",
# "post_code": "3007",
# "country": "Schweiz"
# },
# "delivery_address": {
# "id": 19,
# "salutation": "male",
# "first_name": "Hans",
# "last_name": "Muster",
# "company": "Muster AG",
# "street": "Ruderweg 24",
# "city": "Bern",
# "post_code": "3000",
# "country": "Schweiz"
# },
# "entries": [
# {
# "id": 3433,
# "uri": "\/products\/myskillbox-lernende",
# "url": None,
# "title": "mySkillbox für Lernende ",
# "subtitle": "Lizenz gültig für 4 Jahre",
# "isbn": "978-3-0355-1397-4",
# "slug": "myskillbox-lernende",
# "product_type": "eLehrmittel",
# "product_form": "",
# "cover": "https:\/\/hep-verlag.fra1.digitaloceanspaces.com\/staging\/products\/2921\/978-3-0355-1397-4.jpg",
# "price": 100,
# "price_total": 100,
# "amount": 1,
# "authors": []
# }
# ]
# }
# ]
def active_myskillbox_product_for_customer(self, request=None, token=None):
eorders = self.fetch_eorders(request=request, token=token)
myskillbox_products = self._extract_myskillbox_products(eorders)
if len(myskillbox_products) == 0:
return None
else:
return self._get_active_product(myskillbox_products)
def _has_credentials(self, request, token):
if request is None and token is None:
raise HepClientNoTokenException
def redeem_coupon(self, coupon_code, customer_id, request=None, token=None):
self._has_credentials(request, token)
try:
response = self._call(f'api/partners/users/{customer_id}/coupons/redeem', request, token, method='post',
data={'code': coupon_code})
except HepClientException:
return None
response_data = response.json()
# todo handle 404, 402
return response_data
def _extract_myskillbox_products(self, eorders):
products = []
for eorder in eorders:
status = eorder.get('status', '')
for entry in eorder['entries']:
product = self.entry_to_product(entry, self._get_item_activation(eorder), status)
if product:
products.append(product)
return products
def entry_to_product(self, entry, activation_date, status):
if is_myskillbox_product(entry['isbn']) and activation_date:
return {
'raw': entry,
'activated': activation_date,
'status': status,
'order_id': entry['id'],
'license': MYSKILLBOX_LICENSES[entry['isbn']],
'isbn': entry['isbn']
}
return None
def _get_item_activation(self, eorder):
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 ['paid', 'new']:
return False
expiry_delta = product['activated'] + timedelta(product['license']['duration'])
return License.is_product_active(expiry_delta, product['isbn'])
active_products = list(filter(filter_valid_products, products))
if len(active_products) == 0:
return None
elif len(active_products) == 1:
return active_products[0]
else:
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:
return product
# select a student product, as they are all valid it does not matter which one
return active_products[0]