add logic for checkin
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
parent
d7725ced6f
commit
268c5c7c6d
|
@ -1,10 +1,11 @@
|
||||||
"""AuthenticatorMobileStage API Views"""
|
"""AuthenticatorMobileStage API Views"""
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
|
from django.utils.timezone import now
|
||||||
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
|
||||||
from rest_framework.decorators import action
|
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.filters import OrderingFilter, SearchFilter
|
||||||
from rest_framework.permissions import IsAdminUser
|
from rest_framework.permissions import IsAdminUser
|
||||||
from rest_framework.request import Request
|
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):
|
class MobileDeviceInfoSerializer(PassiveSerializer):
|
||||||
"""Info about a mobile device"""
|
"""Info about a mobile device"""
|
||||||
|
|
||||||
|
@ -47,6 +39,19 @@ class MobileDeviceInfoSerializer(PassiveSerializer):
|
||||||
hostname = CharField()
|
hostname = CharField()
|
||||||
app_version = 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):
|
class MobileDeviceCheckInSerializer(PassiveSerializer):
|
||||||
"""Check info into authentik"""
|
"""Check info into authentik"""
|
||||||
|
@ -213,6 +218,29 @@ class MobileDeviceViewSet(
|
||||||
transaction.save()
|
transaction.save()
|
||||||
return Response(status=204)
|
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):
|
class AdminMobileDeviceViewSet(ModelViewSet):
|
||||||
"""Viewset for Mobile authenticator devices (for admins)"""
|
"""Viewset for Mobile authenticator devices (for admins)"""
|
||||||
|
|
|
@ -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),
|
||||||
|
),
|
||||||
|
]
|
|
@ -93,6 +93,9 @@ class MobileDevice(SerializerModel, Device):
|
||||||
device_id = models.TextField(unique=True)
|
device_id = models.TextField(unique=True)
|
||||||
firebase_token = models.TextField(blank=True)
|
firebase_token = models.TextField(blank=True)
|
||||||
|
|
||||||
|
state = models.JSONField(default=dict)
|
||||||
|
last_checkin = models.DateTimeField(auto_now=True)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer(self) -> Serializer:
|
def serializer(self) -> Serializer:
|
||||||
from authentik.stages.authenticator_mobile.api.device import MobileDeviceSerializer
|
from authentik.stages.authenticator_mobile.api.device import MobileDeviceSerializer
|
||||||
|
@ -108,6 +111,8 @@ class MobileDevice(SerializerModel, Device):
|
||||||
|
|
||||||
|
|
||||||
class TransactionStates(models.TextChoices):
|
class TransactionStates(models.TextChoices):
|
||||||
|
"""States a transaction can be in"""
|
||||||
|
|
||||||
wait = "wait"
|
wait = "wait"
|
||||||
accept = "accept"
|
accept = "accept"
|
||||||
deny = "deny"
|
deny = "deny"
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
"""API URLs"""
|
"""API URLs"""
|
||||||
|
from rest_framework import routers
|
||||||
|
|
||||||
from authentik.stages.authenticator_mobile.api.device import (
|
from authentik.stages.authenticator_mobile.api.device import (
|
||||||
AdminMobileDeviceViewSet,
|
AdminMobileDeviceViewSet,
|
||||||
MobileDeviceViewSet,
|
MobileDeviceViewSet,
|
||||||
)
|
)
|
||||||
from authentik.stages.authenticator_mobile.api.stage import AuthenticatorMobileStageViewSet
|
from authentik.stages.authenticator_mobile.api.stage import AuthenticatorMobileStageViewSet
|
||||||
from rest_framework import routers
|
|
||||||
|
|
||||||
# Separate router which is used for the subset-schema generation
|
# Separate router which is used for the subset-schema generation
|
||||||
# for the cloud-gateway we (currently) only want the mobile device endpoints
|
# for the cloud-gateway we (currently) only want the mobile device endpoints
|
||||||
|
|
|
@ -6040,6 +6040,11 @@
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"title": "Name",
|
"title": "Name",
|
||||||
"description": "The human-readable name of this device."
|
"description": "The human-readable name of this device."
|
||||||
|
},
|
||||||
|
"state": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": true,
|
||||||
|
"title": "State"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
|
79
schema.yml
79
schema.yml
|
@ -2165,6 +2165,43 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
description: ''
|
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/:
|
/authenticators/mobile/{uuid}/enrollment_callback/:
|
||||||
post:
|
post:
|
||||||
operationId: authenticators_mobile_enrollment_callback_create
|
operationId: authenticators_mobile_enrollment_callback_create
|
||||||
|
@ -34271,7 +34308,15 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
|
last_checkin:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/MobileDeviceInfo'
|
||||||
|
readOnly: true
|
||||||
required:
|
required:
|
||||||
|
- last_checkin
|
||||||
- name
|
- name
|
||||||
MobileDeviceEnrollmentCallback:
|
MobileDeviceEnrollmentCallback:
|
||||||
type: object
|
type: object
|
||||||
|
@ -34307,6 +34352,30 @@ components:
|
||||||
description: |-
|
description: |-
|
||||||
* `success` - Success
|
* `success` - Success
|
||||||
* `waiting` - Waiting
|
* `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:
|
MobileDeviceInfoRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Info about a mobile device
|
description: Info about a mobile device
|
||||||
|
@ -34325,11 +34394,15 @@ components:
|
||||||
app_version:
|
app_version:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
|
others:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
required:
|
required:
|
||||||
- app_version
|
- app_version
|
||||||
- hostname
|
- hostname
|
||||||
- model
|
- model
|
||||||
- os_version
|
- os_version
|
||||||
|
- others
|
||||||
- platform
|
- platform
|
||||||
MobileDeviceRequest:
|
MobileDeviceRequest:
|
||||||
type: object
|
type: object
|
||||||
|
@ -34344,6 +34417,9 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
MobileDeviceResponseRequest:
|
MobileDeviceResponseRequest:
|
||||||
|
@ -38130,6 +38206,9 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
PatchedNotificationRequest:
|
PatchedNotificationRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Notification Serializer
|
description: Notification Serializer
|
||||||
|
|
|
@ -209,6 +209,43 @@ paths:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/GenericError'
|
$ref: '#/components/schemas/GenericError'
|
||||||
description: ''
|
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/:
|
/authenticators/mobile/{uuid}/enrollment_callback/:
|
||||||
post:
|
post:
|
||||||
operationId: authenticators_mobile_enrollment_callback_create
|
operationId: authenticators_mobile_enrollment_callback_create
|
||||||
|
@ -435,7 +472,15 @@ components:
|
||||||
type: string
|
type: string
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
|
last_checkin:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/MobileDeviceInfo'
|
||||||
|
readOnly: true
|
||||||
required:
|
required:
|
||||||
|
- last_checkin
|
||||||
- name
|
- name
|
||||||
MobileDeviceEnrollmentCallback:
|
MobileDeviceEnrollmentCallback:
|
||||||
type: object
|
type: object
|
||||||
|
@ -471,6 +516,30 @@ components:
|
||||||
description: |-
|
description: |-
|
||||||
* `success` - Success
|
* `success` - Success
|
||||||
* `waiting` - Waiting
|
* `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:
|
MobileDeviceInfoRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Info about a mobile device
|
description: Info about a mobile device
|
||||||
|
@ -489,11 +558,15 @@ components:
|
||||||
app_version:
|
app_version:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
|
others:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
required:
|
required:
|
||||||
- app_version
|
- app_version
|
||||||
- hostname
|
- hostname
|
||||||
- model
|
- model
|
||||||
- os_version
|
- os_version
|
||||||
|
- others
|
||||||
- platform
|
- platform
|
||||||
MobileDeviceRequest:
|
MobileDeviceRequest:
|
||||||
type: object
|
type: object
|
||||||
|
@ -508,6 +581,9 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
MobileDeviceResponseRequest:
|
MobileDeviceResponseRequest:
|
||||||
|
@ -591,6 +667,9 @@ components:
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: The human-readable name of this device.
|
description: The human-readable name of this device.
|
||||||
maxLength: 64
|
maxLength: 64
|
||||||
|
state:
|
||||||
|
type: object
|
||||||
|
additionalProperties: {}
|
||||||
PlatformEnum:
|
PlatformEnum:
|
||||||
enum:
|
enum:
|
||||||
- ios
|
- ios
|
||||||
|
|
Reference in New Issue