add logic for checkin

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2023-09-05 15:16:00 +02:00
parent d7725ced6f
commit 268c5c7c6d
No known key found for this signature in database
7 changed files with 230 additions and 11 deletions

View File

@ -1,10 +1,11 @@
"""AuthenticatorMobileStage API Views"""
from django.http import Http404
from django.utils.timezone import now
from django_filters.rest_framework.backends import DjangoFilterBackend
from drf_spectacular.utils import OpenApiResponse, extend_schema, inline_serializer
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.fields import CharField, ChoiceField, UUIDField
from rest_framework.fields import CharField, ChoiceField, JSONField, UUIDField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
@ -24,15 +25,6 @@ from authentik.stages.authenticator_mobile.models import (
)
class MobileDeviceSerializer(ModelSerializer):
"""Serializer for Mobile authenticator devices"""
class Meta:
model = MobileDevice
fields = ["pk", "name"]
depth = 2
class MobileDeviceInfoSerializer(PassiveSerializer):
"""Info about a mobile device"""
@ -47,6 +39,19 @@ class MobileDeviceInfoSerializer(PassiveSerializer):
hostname = CharField()
app_version = CharField()
others = JSONField()
class MobileDeviceSerializer(ModelSerializer):
"""Serializer for Mobile authenticator devices"""
last_checkin = MobileDeviceInfoSerializer(read_only=True)
class Meta:
model = MobileDevice
fields = ["pk", "name", "state", "last_checkin"]
depth = 2
class MobileDeviceCheckInSerializer(PassiveSerializer):
"""Check info into authentik"""
@ -213,6 +218,29 @@ class MobileDeviceViewSet(
transaction.save()
return Response(status=204)
@extend_schema(
responses={
204: OpenApiResponse(description="Checked in"),
},
request=MobileDeviceInfoSerializer,
)
@action(
methods=["POST"],
detail=True,
permission_classes=[],
filter_backends=[],
authentication_classes=[MobileDeviceTokenAuthentication],
)
def check_in(self, request: Request, pk: str) -> Response:
"""Check in data about a device"""
data = MobileDeviceInfoSerializer(data=request.data)
data.is_valid(raise_exception=True)
device: MobileDevice = self.get_object()
device.last_checkin = now()
device.state = data.validated_data
device.save()
return Response(status=204)
class AdminMobileDeviceViewSet(ModelViewSet):
"""Viewset for Mobile authenticator devices (for admins)"""

View File

@ -0,0 +1,22 @@
# Generated by Django 4.2.4 on 2023-09-05 13:16
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_stages_authenticator_mobile", "0003_mobiletransaction_status"),
]
operations = [
migrations.AddField(
model_name="mobiledevice",
name="last_checkin",
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name="mobiledevice",
name="state",
field=models.JSONField(default=dict),
),
]

View File

@ -93,6 +93,9 @@ class MobileDevice(SerializerModel, Device):
device_id = models.TextField(unique=True)
firebase_token = models.TextField(blank=True)
state = models.JSONField(default=dict)
last_checkin = models.DateTimeField(auto_now=True)
@property
def serializer(self) -> Serializer:
from authentik.stages.authenticator_mobile.api.device import MobileDeviceSerializer
@ -108,6 +111,8 @@ class MobileDevice(SerializerModel, Device):
class TransactionStates(models.TextChoices):
"""States a transaction can be in"""
wait = "wait"
accept = "accept"
deny = "deny"

View File

@ -1,10 +1,11 @@
"""API URLs"""
from rest_framework import routers
from authentik.stages.authenticator_mobile.api.device import (
AdminMobileDeviceViewSet,
MobileDeviceViewSet,
)
from authentik.stages.authenticator_mobile.api.stage import AuthenticatorMobileStageViewSet
from rest_framework import routers
# Separate router which is used for the subset-schema generation
# for the cloud-gateway we (currently) only want the mobile device endpoints

View File

@ -6040,6 +6040,11 @@
"minLength": 1,
"title": "Name",
"description": "The human-readable name of this device."
},
"state": {
"type": "object",
"additionalProperties": true,
"title": "State"
}
},
"required": []

View File

@ -2165,6 +2165,43 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{uuid}/check_in/:
post:
operationId: authenticators_mobile_check_in_create
description: Check in data about a device
parameters:
- in: path
name: uuid
schema:
type: string
format: uuid
description: A UUID string identifying this Mobile Device.
required: true
tags:
- authenticators
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceInfoRequest'
required: true
security:
- mobile_device_token: []
responses:
'204':
description: Checked in
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{uuid}/enrollment_callback/:
post:
operationId: authenticators_mobile_enrollment_callback_create
@ -34271,7 +34308,15 @@ components:
type: string
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
last_checkin:
allOf:
- $ref: '#/components/schemas/MobileDeviceInfo'
readOnly: true
required:
- last_checkin
- name
MobileDeviceEnrollmentCallback:
type: object
@ -34307,6 +34352,30 @@ components:
description: |-
* `success` - Success
* `waiting` - Waiting
MobileDeviceInfo:
type: object
description: Info about a mobile device
properties:
platform:
$ref: '#/components/schemas/PlatformEnum'
os_version:
type: string
model:
type: string
hostname:
type: string
app_version:
type: string
others:
type: object
additionalProperties: {}
required:
- app_version
- hostname
- model
- os_version
- others
- platform
MobileDeviceInfoRequest:
type: object
description: Info about a mobile device
@ -34325,11 +34394,15 @@ components:
app_version:
type: string
minLength: 1
others:
type: object
additionalProperties: {}
required:
- app_version
- hostname
- model
- os_version
- others
- platform
MobileDeviceRequest:
type: object
@ -34344,6 +34417,9 @@ components:
minLength: 1
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
required:
- name
MobileDeviceResponseRequest:
@ -38130,6 +38206,9 @@ components:
minLength: 1
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
PatchedNotificationRequest:
type: object
description: Notification Serializer

View File

@ -209,6 +209,43 @@ paths:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{uuid}/check_in/:
post:
operationId: authenticators_mobile_check_in_create
description: Check in data about a device
parameters:
- in: path
name: uuid
schema:
type: string
format: uuid
description: A UUID string identifying this Mobile Device.
required: true
tags:
- authenticators
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/MobileDeviceInfoRequest'
required: true
security:
- mobile_device_token: []
responses:
'204':
description: Checked in
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/ValidationError'
description: ''
'403':
content:
application/json:
schema:
$ref: '#/components/schemas/GenericError'
description: ''
/authenticators/mobile/{uuid}/enrollment_callback/:
post:
operationId: authenticators_mobile_enrollment_callback_create
@ -435,7 +472,15 @@ components:
type: string
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
last_checkin:
allOf:
- $ref: '#/components/schemas/MobileDeviceInfo'
readOnly: true
required:
- last_checkin
- name
MobileDeviceEnrollmentCallback:
type: object
@ -471,6 +516,30 @@ components:
description: |-
* `success` - Success
* `waiting` - Waiting
MobileDeviceInfo:
type: object
description: Info about a mobile device
properties:
platform:
$ref: '#/components/schemas/PlatformEnum'
os_version:
type: string
model:
type: string
hostname:
type: string
app_version:
type: string
others:
type: object
additionalProperties: {}
required:
- app_version
- hostname
- model
- os_version
- others
- platform
MobileDeviceInfoRequest:
type: object
description: Info about a mobile device
@ -489,11 +558,15 @@ components:
app_version:
type: string
minLength: 1
others:
type: object
additionalProperties: {}
required:
- app_version
- hostname
- model
- os_version
- others
- platform
MobileDeviceRequest:
type: object
@ -508,6 +581,9 @@ components:
minLength: 1
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
required:
- name
MobileDeviceResponseRequest:
@ -591,6 +667,9 @@ components:
minLength: 1
description: The human-readable name of this device.
maxLength: 64
state:
type: object
additionalProperties: {}
PlatformEnum:
enum:
- ios