from urllib.parse import urlencode from uuid import uuid4 import logging 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.utils.dateparse import parse_datetime import withings.api import withings.models import gotify.api import gotify.models from medwings.forms import ProfileForm from .forms import CustomUserCreationForm 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 request.session.flush() 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): if request.user.is_authenticated: raise PermissionDenied('You are already registered and logged in.') authorization_code = request.GET.get('code') authorization_state = request.GET.get('state') if not authorization_code: return HttpResponseBadRequest() if not authorization_state: return HttpResponseBadRequest() if not request.session.get('spoof_protection_token', None) == authorization_state: return HttpResponseBadRequest() if request.method == 'GET': # Fetch access and refresh tokens and save them to session storage redirect_uri = request.build_absolute_uri(reverse('register-continue')) response_data = withings.api.fetch_initial_tokens(authorization_code, redirect_uri) if response_data['status'] != 0: return HttpResponseBadRequest() withings.api.save_tokens_to_session(request, response_data) user_form = CustomUserCreationForm() profile_form = ProfileForm() else: user_form = CustomUserCreationForm(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.api.upload_application_picture(user.username, user_password, gotify_app_info['id']) 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() request.session.flush() withings_api_account.update_records() # TODO redirect user to some other page and ask them to log in return redirect('dashboard') context = { 'user_form': user_form, 'profile_form': profile_form, } return render(request, 'authentication/register-continue.html', context) def register_finalize(request): if request.user.is_authenticated: raise PermissionDenied('You are already registered and logged in.') # TODO implement return render(request, 'authentication/register-finalize.html')