hotpocket/services/backend/hotpocket_backend/apps/ui/views/integrations/extension.py

106 lines
3.3 KiB
Python

# -*- 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')