feat: add device registration observation
This commit is contained in:
@@ -27,6 +27,7 @@ from apps.api.image_tasks import (
|
||||
from apps.api.models import ImageGenerationTask
|
||||
from apps.api.serializers import (
|
||||
AnalyzeImagesRequestSerializer,
|
||||
DeviceRegistrationRequestSerializer,
|
||||
GenerateImageRequestSerializer,
|
||||
GenerateTitleRequestSerializer,
|
||||
RechargeCreateRequestSerializer,
|
||||
@@ -63,6 +64,12 @@ from apps.billing.services import (
|
||||
query_and_apply_recharge_payment,
|
||||
)
|
||||
from apps.portal.models import DownloadRelease
|
||||
from apps.licensing.authentication import DeviceSessionAuthentication
|
||||
from apps.licensing.services import (
|
||||
DeviceRegistrationError,
|
||||
record_device_heartbeat,
|
||||
register_device,
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -263,6 +270,82 @@ class ModelsView(ExternalApiView):
|
||||
)
|
||||
|
||||
|
||||
def _device_response(device) -> dict:
|
||||
return {
|
||||
"product_code": device.product_code,
|
||||
"platform": device.platform,
|
||||
"client_version": device.client_version,
|
||||
"status": device.status,
|
||||
"first_seen_at": device.first_seen_at.isoformat(),
|
||||
"last_seen_at": device.last_seen_at.isoformat(),
|
||||
}
|
||||
|
||||
|
||||
class DeviceRegistrationView(ExternalApiView):
|
||||
def post(self, request):
|
||||
serializer = DeviceRegistrationRequestSerializer(data=request.data)
|
||||
if not serializer.is_valid():
|
||||
return Response(
|
||||
api_error("bad_request", "参数错误"),
|
||||
status=status.HTTP_400_BAD_REQUEST,
|
||||
)
|
||||
data = serializer.validated_data
|
||||
try:
|
||||
result = register_device(
|
||||
user=request.user,
|
||||
api_key=request.auth,
|
||||
product_code=data["product_code"],
|
||||
device_id_version=data["device_id_version"],
|
||||
device_id=data["device_id"],
|
||||
public_key=data["installation_public_key"],
|
||||
platform=data["platform"],
|
||||
client_version=data["client_version"],
|
||||
)
|
||||
except DeviceRegistrationError as exc:
|
||||
return Response(
|
||||
api_error(exc.code, exc.message),
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
return Response(
|
||||
{
|
||||
"device": _device_response(result.device),
|
||||
"device_session_token": result.session_token,
|
||||
"expires_at": result.session.expires_at.isoformat(),
|
||||
},
|
||||
status=status.HTTP_201_CREATED if result.created else status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
class DeviceSessionApiView(APIView):
|
||||
authentication_classes = (DeviceSessionAuthentication,)
|
||||
permission_classes = (IsAuthenticated,)
|
||||
|
||||
def permission_denied(self, request, message=None, code=None):
|
||||
if request.authenticators and not request.successful_authenticator:
|
||||
raise DeviceSessionAuthentication.authentication_failed(request)
|
||||
super().permission_denied(request, message=message, code=code)
|
||||
|
||||
|
||||
class DeviceHeartbeatView(DeviceSessionApiView):
|
||||
def post(self, request):
|
||||
try:
|
||||
updated = record_device_heartbeat(request.auth)
|
||||
except DeviceRegistrationError as exc:
|
||||
return Response(
|
||||
api_error(exc.code, exc.message),
|
||||
status=status.HTTP_403_FORBIDDEN,
|
||||
)
|
||||
request.auth.device.refresh_from_db()
|
||||
return Response(
|
||||
{
|
||||
"device": _device_response(request.auth.device),
|
||||
"activity_updated": updated,
|
||||
"expires_at": request.auth.expires_at.isoformat(),
|
||||
},
|
||||
status=status.HTTP_200_OK,
|
||||
)
|
||||
|
||||
|
||||
def _release_unpublished_response(platform: str) -> dict:
|
||||
return {
|
||||
"platform": platform,
|
||||
|
||||
Reference in New Issue
Block a user