# -*- coding: utf-8 -*- from __future__ import annotations import logging import urllib.parse import uuid from django import db from django.core.exceptions import PermissionDenied from django.http import HttpRequest, HttpResponse from django.shortcuts import redirect, render from django.urls import reverse from hotpocket_backend.apps.ui.constants import AuthSource from hotpocket_soa.services import AuthKeysService LOGGER = logging.getLogger(__name__) SOURCE_TO_REDIRECT_SCHEME = { AuthSource.DESKTOP.value: 'hotpocket-desktop', AuthSource.MOBILE.value: 'hotpocket-mobile', } def authenticate(request: HttpRequest) -> HttpResponse: source = request.GET.get( 'source', request.session.get('extension_source', AuthSource.BROWSER_EXTENSION.value), ) session_token = request.GET.get( 'session_token', request.session.get('extension_session_token', None), ) if source == AuthSource.BROWSER_EXTENSION.value: session_token = str(uuid.uuid4()) elif source in (AuthSource.DESKTOP.value, AuthSource.MOBILE.value): assert session_token not in ('', None), 'Session token missing' else: raise ValueError(f'Unknown source: `{source}`') request.session['extension_source'] = source request.session['extension_session_token'] = session_token request.session.save() if request.user.is_anonymous is False: with db.transaction.atomic(): auth_key = AuthKeysService().create( account_uuid=request.user.pk, ) return redirect(reverse( 'ui.integrations.extension.post_authenticate', query=[ ('auth_key', auth_key.key), ], )) return redirect(reverse('ui.accounts.login', query=[ ('next', reverse('ui.integrations.extension.authenticate')), ])) def post_authenticate(request: HttpRequest) -> HttpResponse: try: assert request.user.is_anonymous is False, 'Not authenticated' auth_key = request.GET.get('auth_key', None) assert auth_key is not None, 'Auth key missing' source = request.session.get('extension_source', None) assert source is not None, 'Source is missing' session_token = request.session.get('extension_session_token', None) assert session_token is not None, 'Session token is missing' app_redirect_url = None if source in (AuthSource.DESKTOP.value, AuthSource.MOBILE.value): app_redirect_url = urllib.parse.urlunsplit(( SOURCE_TO_REDIRECT_SCHEME[source], 'post-authenticate', '/', urllib.parse.urlencode([ ('session_token', session_token), ('auth_key', auth_key), ]), '', )) request.session.pop('extension_source') request.session.pop('extension_session_token') request.session.save() return render( request, 'ui/integrations/extension/post_authenticate.html', { 'app_redirect_url': app_redirect_url, }, ) except AssertionError as exception: LOGGER.error( 'Unable to handle extension authentication: %s', exception, exc_info=exception, ) raise PermissionDenied('NOPE')