add transaction states

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-09-04 20:29:26 +02:00
parent a84f76be4d
commit cda379f4ba
No known key found for this signature in database
5 changed files with 54 additions and 17 deletions

View File

@ -1,5 +1,5 @@
"""AuthenticatorMobileStage API Views""" """AuthenticatorMobileStage API Views"""
from django.utils.translation import gettext_lazy as _ from django.http import Http404
from django_filters.rest_framework.backends import DjangoFilterBackend from django_filters.rest_framework.backends import DjangoFilterBackend
from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer
from rest_framework import mixins from rest_framework import mixins
@ -16,7 +16,12 @@ from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer from authentik.core.api.utils import PassiveSerializer
from authentik.stages.authenticator_mobile.api.auth import MobileDeviceTokenAuthentication from authentik.stages.authenticator_mobile.api.auth import MobileDeviceTokenAuthentication
from authentik.stages.authenticator_mobile.models import MobileDevice, MobileDeviceToken from authentik.stages.authenticator_mobile.models import (
MobileDevice,
MobileDeviceToken,
MobileTransaction,
TransactionStates,
)
class MobileDeviceSerializer(ModelSerializer): class MobileDeviceSerializer(ModelSerializer):
@ -66,16 +71,7 @@ class MobileDeviceResponseSerializer(PassiveSerializer):
tx_id = CharField(required=True) tx_id = CharField(required=True)
status = ChoiceField( status = ChoiceField(
( TransactionStates.choices,
(
"accept",
_("Accept"),
),
(
"deny",
_("Deny"),
),
),
required=True, required=True,
) )
@ -193,6 +189,7 @@ class MobileDeviceViewSet(
@extend_schema( @extend_schema(
responses={ responses={
204: OpenApiResponse(description="Key successfully set"), 204: OpenApiResponse(description="Key successfully set"),
404: OpenApiResponse(description="Transaction not found"),
}, },
request=MobileDeviceResponseSerializer, request=MobileDeviceResponseSerializer,
) )
@ -205,7 +202,12 @@ class MobileDeviceViewSet(
) )
def receive_response(self, request: Request, pk: str) -> Response: def receive_response(self, request: Request, pk: str) -> Response:
"""Get response from notification on phone""" """Get response from notification on phone"""
print(request.data) data = MobileDeviceResponseSerializer(data=request.data)
data.is_valid()
transaction = MobileTransaction.objects.filter(tx_id=data.validated_data["tx_id"]).first()
if not transaction:
raise Http404
transaction.status = data.validated_data["status"]
return Response(status=204) return Response(status=204)

View File

@ -1,10 +1,12 @@
# Generated by Django 4.2.4 on 2023-09-04 18:18 # Generated by Django 4.2.4 on 2023-09-04 18:18
import authentik.core.models
from django.db import migrations, models
import django.db.models.deletion
import uuid import uuid
import django.db.models.deletion
from django.db import migrations, models
import authentik.core.models
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [

View File

@ -0,0 +1,19 @@
# Generated by Django 4.2.4 on 2023-09-04 18:28
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_authenticator_mobile", "0002_mobiletransaction"),
]
operations = [
migrations.AddField(
model_name="mobiletransaction",
name="status",
field=models.TextField(
choices=[("wait", "Wait"), ("accept", "Accept"), ("deny", "Deny")], default="wait"
),
),
]

View File

@ -106,12 +106,20 @@ class MobileDevice(SerializerModel, Device):
verbose_name_plural = _("Mobile Devices") verbose_name_plural = _("Mobile Devices")
class TransactionStates(models.TextChoices):
wait = "wait"
accept = "accept"
deny = "deny"
class MobileTransaction(ExpiringModel): class MobileTransaction(ExpiringModel):
"""A single push transaction""" """A single push transaction"""
tx_id = models.UUIDField(default=uuid4, primary_key=True) tx_id = models.UUIDField(default=uuid4, primary_key=True)
device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE) device = models.ForeignKey(MobileDevice, on_delete=models.CASCADE)
status = models.TextField(choices=TransactionStates.choices, default=TransactionStates.wait)
def send_message(self, request: Optional[HttpRequest], **context): def send_message(self, request: Optional[HttpRequest], **context):
"""Send mobile message""" """Send mobile message"""
branding = DEFAULT_TENANT.branding_title branding = DEFAULT_TENANT.branding_title
@ -120,6 +128,9 @@ class MobileTransaction(ExpiringModel):
branding = request.tenant.branding_title branding = request.tenant.branding_title
domain = request.get_host() domain = request.get_host()
message = Message( message = Message(
data={
"tx_id": str(self.tx_id),
},
notification=Notification( notification=Notification(
title=__("%(brand)s authentication request" % {"brand": branding}), title=__("%(brand)s authentication request" % {"brand": branding}),
body=__( body=__(
@ -144,7 +155,6 @@ class MobileTransaction(ExpiringModel):
category="cat_authentik_push_authorization", category="cat_authentik_push_authorization",
), ),
interruption_level="time-sensitive", interruption_level="time-sensitive",
tx_id=str(self.tx_id),
), ),
), ),
token=self.device.firebase_token, token=self.device.firebase_token,

View File

@ -2266,6 +2266,8 @@ paths:
responses: responses:
'204': '204':
description: Key successfully set description: Key successfully set
'404':
description: Transaction not found
'400': '400':
content: content:
application/json: application/json:
@ -34354,10 +34356,12 @@ components:
- tx_id - tx_id
MobileDeviceResponseStatusEnum: MobileDeviceResponseStatusEnum:
enum: enum:
- wait
- accept - accept
- deny - deny
type: string type: string
description: |- description: |-
* `wait` - Wait
* `accept` - Accept * `accept` - Accept
* `deny` - Deny * `deny` - Deny
MobileDeviceSetPushKeyRequest: MobileDeviceSetPushKeyRequest: