Re-order structure

This commit is contained in:
Christian Cueni 2021-05-06 09:50:47 +02:00
parent 91fa976317
commit 549bf1ef28
13 changed files with 138 additions and 150 deletions

View File

@ -6,7 +6,7 @@ from graphene_django.views import GraphQLView
from api.schema_public import schema from api.schema_public import schema
from core.views import PrivateGraphQLView, ConfirmationKeyDisplayView from core.views import PrivateGraphQLView
app_name = 'api' app_name = 'api'
urlpatterns = [ urlpatterns = [
@ -21,6 +21,5 @@ if settings.DEBUG:
urlpatterns += [url(r'^graphiql-public', csrf_exempt(GraphQLView.as_view(schema=schema, graphiql=True, urlpatterns += [url(r'^graphiql-public', csrf_exempt(GraphQLView.as_view(schema=schema, graphiql=True,
pretty=True)))] pretty=True)))]
urlpatterns += [url(r'^graphiql', csrf_exempt(PrivateGraphQLView.as_view(graphiql=True, pretty=True)))] urlpatterns += [url(r'^graphiql', csrf_exempt(PrivateGraphQLView.as_view(graphiql=True, pretty=True)))]
urlpatterns += [url(r'^confirmation', ConfirmationKeyDisplayView.as_view(), name='confirmation_key_display')]

View File

@ -3,28 +3,13 @@ from django.db import models
from datetime import timedelta from datetime import timedelta
from django.utils import timezone from django.utils import timezone
from core.hep_client import HepClient
DEFAULT_PK = 1 DEFAULT_PK = 1
class AdminDataManager(models.Manager): class AdminDataManager(models.Manager):
hep_client = HepClient()
def update_admin_token(self): def update_admin_token(self):
admin_token = self.hep_client.fetch_admin_token(settings.HEP_ADMIN_USER, settings.HEP_ADMIN_PASSWORD) return ''
admin_data, created = self.get_or_create(pk=DEFAULT_PK)
admin_data.hep_admin_token = admin_token
admin_data.save()
return admin_data.hep_admin_token
def get_admin_token(self): def get_admin_token(self):
try: return ''
admin_token = self.get(pk=DEFAULT_PK)
if admin_token.updated_at < timezone.now() + timedelta(hours=1):
admin_token = self.update_admin_token()
except self.model.DoesNotExist:
admin_token = self.update_admin_token()
return admin_token

View File

@ -416,7 +416,7 @@ AUTHLIB_OAUTH_CLIENTS = {
'authorize_url': os.environ.get("OAUTH_AUTHORIZE_URL"), 'authorize_url': os.environ.get("OAUTH_AUTHORIZE_URL"),
'api_base_url': os.environ.get("OAUTH_API_BASE_URL"), 'api_base_url': os.environ.get("OAUTH_API_BASE_URL"),
'client_kwargs': { 'client_kwargs': {
'scope': 'email', 'scope': 'orders',
'token_endpoint_auth_method': 'client_secret_post', 'token_endpoint_auth_method': 'client_secret_post',
'token_placement': 'header', 'token_placement': 'header',
} }

View File

@ -7,7 +7,6 @@ from django.views.decorators.csrf import ensure_csrf_cookie
from django.views.generic import TemplateView from django.views.generic import TemplateView
from graphene_django.views import GraphQLView from graphene_django.views import GraphQLView
from core.hep_client import HepClient
from core.models import AdminData from core.models import AdminData
@ -27,20 +26,3 @@ def home(request):
print('Can not connect to dev server at http://localhost:8080:', e) print('Can not connect to dev server at http://localhost:8080:', e)
return render(request, 'index.html', {}) return render(request, 'index.html', {})
class ConfirmationKeyDisplayView(TemplateView):
template_name = 'confirmation_key.html'
def get_context_data(self, *args, **kwargs):
email = self.request.GET.get('email', '')
hep_client = HepClient()
admin_token = AdminData.objects.get_admin_token()
hep_user = hep_client.customers_search(admin_token, email)
context = super().get_context_data(**kwargs)
context['confirmation_key'] = hep_user['confirmation']
context['hep_id'] = hep_user['id']
return context

View File

@ -4,42 +4,11 @@ from django.conf import settings
import logging import logging
import requests import requests
from core.oauth import oauth from oauth.oauth_client import oauth
from users.models import License
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
TEACHER_KEY = 'teacher'
STUDENT_KEY = 'student'
MYSKILLBOX_LICENSES = {
"978-3-0355-1397-4": {
'edition': STUDENT_KEY,
'duration': 4 * 365,
'name': 'Student 4 years'
},
"978-3-0355-1860-3": {
'edition': STUDENT_KEY,
'duration': 455,
'name': 'Student 1 year'
},
"978-3-0355-1862-7": {
'edition': STUDENT_KEY,
'duration': 30,
'name': 'Student test 1 month'
},
"978-3-0355-1861-0": {
'edition': TEACHER_KEY,
'duration': 30,
'name': 'Teacher test 1 month'
},
"978-3-0355-1823-8": {
'edition': TEACHER_KEY,
'duration': 455,
'name': 'Teacher 1 year'
}
}
class HepClientException(Exception): class HepClientException(Exception):
pass pass
@ -48,6 +17,10 @@ class HepClientUnauthorizedException(Exception):
pass pass
class HepClientNoTokenException(Exception):
pass
class HepClient: class HepClient:
URL = settings.HEP_URL URL = settings.HEP_URL
WEBSITE_ID = 1 WEBSITE_ID = 1
@ -56,14 +29,19 @@ class HepClient:
'content-type': 'application/json' 'content-type': 'application/json'
} }
def _call(self, url, token, method='get', data=None): def _call(self, url, method='get', data=None, request=None, token=None):
request_url = f'{self.URL}{url}' request_url = f'{self.URL}{url}'
token_parameters = {
'token': token,
'request': request
}
if method == 'post': if method == 'post':
response = requests.post(request_url, json=data) response = requests.post(request_url, json=data)
elif method == 'get': elif method == 'get':
response = oauth.hep.get(url, token=token) response = oauth.hep.get(url, **token_parameters)
elif method == 'put': elif method == 'put':
response = requests.put(request_url, data=data) response = requests.put(request_url, data=data)
@ -78,8 +56,10 @@ class HepClient:
def is_email_verified(self, user_data): 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, token): def user_details(self, request=None, token=None):
response = self._call('/api/auth/user', token) if request is None and token is None:
raise HepClientNoTokenException
response = self._call('/api/auth/user', request=request, token=token)
return response.json()['data'] return response.json()['data']
def customers_search(self, admin_token, email): def customers_search(self, admin_token, email):
@ -167,7 +147,7 @@ class HepClient:
expiry_delta = product['activated'] + timedelta(product['license']['duration']) expiry_delta = product['activated'] + timedelta(product['license']['duration'])
if HepClient.is_product_active(expiry_delta, product['isbn']): if License.is_product_active(expiry_delta, product['isbn']):
return True return True
else: else:
return False return False
@ -196,8 +176,3 @@ class HepClient:
return teacher_edition return teacher_edition
@staticmethod
def is_product_active(expiry_date, isbn):
now = datetime.now()
return expiry_date >= now >= expiry_date - timedelta(days=MYSKILLBOX_LICENSES[isbn]['duration'])

View File

@ -2,7 +2,20 @@
from authlib.integrations.django_client import OAuth from authlib.integrations.django_client import OAuth
from django.conf import settings from django.conf import settings
oauth = OAuth() from oauth.models import OAuth2Token
def fetch_token(name, request):
try:
token = OAuth2Token.objects.get(
user=request.user
)
return token.to_token()
except (OAuth2Token.DoesNotExist, TypeError):
return None
oauth = OAuth(fetch_token=fetch_token)
oauth.register( oauth.register(
name='hep', name='hep',
client_id=settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_id'], client_id=settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_id'],
@ -17,4 +30,3 @@ oauth.register(
client_kwargs=settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_kwargs'], client_kwargs=settings.AUTHLIB_OAUTH_CLIENTS['hep']['client_kwargs'],
) )

View File

@ -1,5 +1,5 @@
from core.hep_client import HepClient, HepClientException
from core.models import AdminData from core.models import AdminData
from oauth.hep_client import HepClient, HepClientException
from users.models import License from users.models import License
from users.models import User, UserRole, Role, SchoolClass from users.models import User, UserRole, Role, SchoolClass
@ -23,18 +23,18 @@ def handle_user_and_verify_products(user_data, ):
except HepClientException: except HepClientException:
return user, UNKNOWN_ERROR return user, UNKNOWN_ERROR
# license = License.objects.get_active_license_for_user(user) license = License.objects.get_active_license_for_user(user)
#
# if not license: if not license:
# license, error_msg = check_and_create_licenses(hep_client, user) license, error_msg = check_and_create_licenses(hep_client, user)
#
# if error_msg: if error_msg:
# return user, error_msg return user, error_msg
#
# create_role_for_user(user, license.for_role.key) create_role_for_user(user, license.for_role.key)
#
# if not license.is_valid(): if not license.is_valid():
# return user, NO_VALID_LICENSE return user, NO_VALID_LICENSE
return user, None return user, None

View File

@ -1,10 +1,10 @@
from django.conf import settings from django.conf import settings
from django.shortcuts import redirect from django.shortcuts import redirect
from core.hep_client import HepClient from oauth.hep_client import HepClient
from core.oauth import oauth from oauth.oauth_client import oauth
from oauth.models import OAuth2Token from oauth.models import OAuth2Token
from users.user_signup_login_handler import handle_user_and_verify_products, EMAIL_NOT_VERIFIED from oauth.user_signup_login_handler import handle_user_and_verify_products, EMAIL_NOT_VERIFIED
from django.contrib.auth import login as dj_login from django.contrib.auth import login as dj_login
@ -17,7 +17,7 @@ def login(request):
def authorize(request): def authorize(request):
hep_client = HepClient() hep_client = HepClient()
token = oauth.hep.authorize_access_token(request) token = oauth.hep.authorize_access_token(request)
user_data = hep_client.user_details(token) user_data = hep_client.user_details(token=token)
user, status_msg = handle_user_and_verify_products(user_data) user, status_msg = handle_user_and_verify_products(user_data)
user.sync_with_hep_data(user_data) user.sync_with_hep_data(user_data)

View File

@ -11,9 +11,9 @@ import graphene
from django.contrib.auth import login from django.contrib.auth import login
from graphene import relay from graphene import relay
from core.hep_client import HepClient, HepClientException # from core.hep_client import HepClient, HepClientException
from core.models import AdminData from core.models import AdminData
from users.user_signup_login_handler import handle_user_and_verify_products, UNKNOWN_ERROR, NO_VALID_LICENSE from oauth.user_signup_login_handler import handle_user_and_verify_products, UNKNOWN_ERROR, NO_VALID_LICENSE
class Registration(relay.ClientIDMutation): class Registration(relay.ClientIDMutation):
@ -30,29 +30,29 @@ class Registration(relay.ClientIDMutation):
confirmation_key = kwargs.get('confirmation_key') confirmation_key = kwargs.get('confirmation_key')
user_id = kwargs.get('user_id') user_id = kwargs.get('user_id')
hep_client = HepClient() # hep_client = HepClient()
admin_token = AdminData.objects.get_admin_token() # admin_token = AdminData.objects.get_admin_token()
try: # try:
hep_client.customer_activate(confirmation_key, user_id) # hep_client.customer_activate(confirmation_key, user_id)
user_data = hep_client.customers_by_id(admin_token, user_id) # user_data = hep_client.customers_by_id(admin_token, user_id)
# double check if user has verified his email. If the "confirmation" field is present, the email address # # double check if user has verified his email. If the "confirmation" field is present, the email address
# is not verified. # # is not verified.
if 'confirmation' in user_data: # if 'confirmation' in user_data:
return cls.return_fail_registration_msg('invalid_key') # return cls.return_fail_registration_msg('invalid_key')
except HepClientException: # except HepClientException:
return cls.return_fail_registration_msg('unknown_error') # return cls.return_fail_registration_msg('unknown_error')
#
# user, status_msg = handle_user_and_verify_products(user_data)
user, status_msg = handle_user_and_verify_products(user_data) # if user:
# login(info.context, user)
if user: #
login(info.context, user) # if status_msg:
# if status_msg == NO_VALID_LICENSE:
if status_msg: # return cls(success=True, message=NO_VALID_LICENSE)
if status_msg == NO_VALID_LICENSE: # else:
return cls(success=True, message=NO_VALID_LICENSE) # return cls.return_fail_registration_msg(status_msg)
else:
return cls.return_fail_registration_msg(status_msg)
return cls(success=True, message='success') return cls(success=True, message='success')

30
server/users/licenses.py Normal file
View File

@ -0,0 +1,30 @@
TEACHER_KEY = 'teacher'
STUDENT_KEY = 'student'
MYSKILLBOX_LICENSES = {
"978-3-0355-1397-4": {
'edition': STUDENT_KEY,
'duration': 4 * 365,
'name': 'Student 4 years'
},
"978-3-0355-1860-3": {
'edition': STUDENT_KEY,
'duration': 365,
'name': 'Student 1 year'
},
"978-3-0355-1862-7": {
'edition': STUDENT_KEY,
'duration': 30,
'name': 'Student test 1 month'
},
"978-3-0355-1861-0": {
'edition': TEACHER_KEY,
'duration': 30,
'name': 'Teacher test 1 month'
},
"978-3-0355-1823-8": {
'edition': TEACHER_KEY,
'duration': 365,
'name': 'Teacher 1 year'
}
}

View File

@ -9,7 +9,7 @@ from django.utils.translation import ugettext_lazy as _
from django.db import models from django.db import models
from django.contrib.auth.models import UserManager as DjangoUserManager from django.contrib.auth.models import UserManager as DjangoUserManager
from core.hep_client import MYSKILLBOX_LICENSES from users.licenses import MYSKILLBOX_LICENSES
class RoleManager(models.Manager): class RoleManager(models.Manager):

View File

@ -1,7 +1,7 @@
import random import random
import re import re
from datetime import datetime, timedelta, date
import string import string
from datetime import date, datetime
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.contrib.auth.models import AbstractUser, Permission from django.contrib.auth.models import AbstractUser, Permission
@ -9,7 +9,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from core.hep_client import HepClient, MYSKILLBOX_LICENSES from users.licenses import MYSKILLBOX_LICENSES
from users.managers import RoleManager, UserRoleManager, UserManager, LicenseManager from users.managers import RoleManager, UserRoleManager, UserManager, LicenseManager
DEFAULT_SCHOOL_ID = 1 DEFAULT_SCHOOL_ID = 1
@ -306,9 +306,15 @@ class License(models.Model):
return self.for_role.key == RoleManager.TEACHER_KEY return self.for_role.key == RoleManager.TEACHER_KEY
def is_valid(self): def is_valid(self):
return HepClient.is_product_active( return License.is_product_active(
datetime(self.expire_date.year, self.expire_date.month, self.expire_date.day), self.isbn) datetime(self.expire_date.year, self.expire_date.month, self.expire_date.day), self.isbn)
@staticmethod
def is_product_active(expiry_date, isbn):
now = datetime.now()
return expiry_date >= now >= expiry_date - timedelta(days=MYSKILLBOX_LICENSES[isbn]['duration'])
def __str__(self): def __str__(self):
return f'License for role: {self.for_role}' return f'License for role: {self.for_role}'

View File

@ -3,8 +3,7 @@ from django.conf import settings
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from graphene import relay from graphene import relay
from core.hep_client import HepClient, HepClientUnauthorizedException, HepClientException # from users.user_signup_login_handler import handle_user_and_verify_products, UNKNOWN_ERROR, EMAIL_NOT_VERIFIED
from users.user_signup_login_handler import handle_user_and_verify_products, UNKNOWN_ERROR, EMAIL_NOT_VERIFIED
class BetaLogin(relay.ClientIDMutation): class BetaLogin(relay.ClientIDMutation):
@ -40,32 +39,32 @@ class Login(relay.ClientIDMutation):
@classmethod @classmethod
def mutate_and_get_payload(cls, root, info, **kwargs): def mutate_and_get_payload(cls, root, info, **kwargs):
hep_client = HepClient() # hep_client = HepClient()
token = kwargs.get('token_input') # token = kwargs.get('token_input')
#
try: # try:
user_data = hep_client.customer_me(token) # user_data = hep_client.customer_me(token)
except HepClientUnauthorizedException: # except HepClientUnauthorizedException:
return cls.return_login_message('invalid_credentials') # return cls.return_login_message('invalid_credentials')
except HepClientException: # except HepClientException:
return cls.return_login_message(UNKNOWN_ERROR) # return cls.return_login_message(UNKNOWN_ERROR)
#
# use in auth # # use in auth
user, status_msg = handle_user_and_verify_products(user_data) # user, status_msg = handle_user_and_verify_products(user_data)
user.sync_with_hep_data(user_data) # user.sync_with_hep_data(user_data)
#
if user and status_msg != EMAIL_NOT_VERIFIED: # if user and status_msg != EMAIL_NOT_VERIFIED:
login(info.context, user) # login(info.context, user)
#
if status_msg: # if status_msg:
return cls.return_login_message(status_msg) # return cls.return_login_message(status_msg)
return cls(success=True, message='success') return cls(success=True, message='success')
@classmethod @classmethod
def return_login_message(cls, message): def return_login_message(cls, message):
if message == EMAIL_NOT_VERIFIED or message == UNKNOWN_ERROR or message == 'invalid_credentials': # if message == EMAIL_NOT_VERIFIED or message == UNKNOWN_ERROR or message == 'invalid_credentials':
raise Exception(message) # raise Exception(message)
return cls(success=True, message=message) return cls(success=True, message=message)