ba-thesis/app/authentication/views.py

126 lines
4.5 KiB
Python

from urllib.parse import urlencode
from uuid import uuid4
from django.shortcuts import redirect, render
from django.conf import settings
from django.urls import reverse
from django.core.exceptions import PermissionDenied
from django.http import HttpResponseBadRequest
from django.contrib.auth.forms import UserCreationForm
from django.utils.dateparse import parse_datetime
import withings.api
import withings.models
import gotify.api
import gotify.models
from medwings.forms import ProfileForm
def register_init(request):
if request.user.is_authenticated:
raise PermissionDenied('You are already registered and logged in.')
# Generate a unique token and save it for later
spoof_protection_token = str(uuid4())
request.session['spoof_protection_token'] = spoof_protection_token
auth_url_base = 'https://account.withings.com/oauth2_user/authorize2'
auth_url_params = {
'response_type': 'code',
'client_id': settings.WITHINGS_CONFIG['CLIENT_ID'],
'scope': 'user.metrics,user.activity',
'redirect_uri': request.build_absolute_uri(reverse('register-continue')),
'state': spoof_protection_token
}
auth_url = f"{auth_url_base}?{urlencode(auth_url_params)}"
context = {
"auth_url": auth_url
}
return render(request, 'authentication/register-init.html', context)
def register_continue(request):
authorization_code = request.GET.get('code')
authorization_state = request.GET.get('state')
if not authorization_code:
return HttpResponseBadRequest()
if not authorization_state:
return HttpResponseBadRequest()
# TODO enable this when not mocking
# if not request.session.get('spoof_protection_token', None) == authorization_state:
# return HttpResponseBadRequest()
# Fetch access and refresh tokens and save them to session storage
redirect_uri = request.build_absolute_uri(reverse('register-continue'))
# DEBUG use an API mock
response_data = withings.api.mock_fetch_withings_tokens(authorization_code, redirect_uri)
if response_data['status'] != 0:
return HttpResponseBadRequest()
withings.api.save_tokens_to_session(request, response_data)
if request.method == 'POST':
user_form = UserCreationForm(request.POST)
profile_form = ProfileForm(request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save(commit=False)
profile = profile_form.save(commit=False)
profile.user = user
user_password = request.POST.get('password1')
gotify_user_info = gotify.api.create_user(user.username, user_password)
gotify_app_info = gotify.api.create_application(user.username, user_password)
gotify_user = gotify.models.GotifyUser(
user=user,
id=gotify_user_info['id']
)
gotify_app = gotify.models.GotifyApplication(
user=gotify_user,
id=gotify_app_info['id'],
token=gotify_app_info['token']
)
withings_api_account = withings.models.ApiAccount(
user=user,
userid=request.session.get('withings_userid')
)
withings_access_token = withings.models.AccessToken(
account=withings_api_account,
value=request.session.get('withings_access_token'),
expires=parse_datetime(request.session.get('withings_access_token_expiry'))
)
withings_refresh_token = withings.models.RefreshToken(
account=withings_api_account,
value=request.session.get('withings_refresh_token'),
expires=parse_datetime(request.session.get('withings_refresh_token_expiry'))
)
for instance in [
user, profile,
gotify_user, gotify_app,
withings_api_account, withings_access_token, withings_refresh_token
]:
instance.save()
# TODO sync withings health data
# TODO redirect user to some other page and ask them to log in
return redirect('dashboard')
else:
user_form = UserCreationForm()
profile_form = ProfileForm()
context = {
'user_form': user_form,
'profile_form': profile_form,
}
return render(request, 'authentication/register-continue.html', context)
def register_finalize(request):
# TODO implement
return render(request, 'authentication/register-finalize.html')