feat: associate generation calls with devices

This commit is contained in:
QiuSW
2026-07-21 09:40:40 +08:00
parent 69f4517958
commit 11c0d63ac8
16 changed files with 398 additions and 19 deletions
+28
View File
@@ -17,6 +17,10 @@ class DeviceRegistrationError(Exception):
super().__init__(message)
class DeviceSessionValidationError(DeviceRegistrationError):
pass
@dataclass(frozen=True)
class DeviceRegistrationResult:
device: ClientDevice
@@ -150,3 +154,27 @@ def record_device_heartbeat(session: DeviceSession, *, now=None) -> bool:
client_version=session.device.client_version,
)
return True
def resolve_optional_device_session(*, user, raw_token: str) -> DeviceSession | None:
raw_token = str(raw_token or "").strip()
if not raw_token:
return None
try:
session = DeviceSession.objects.select_related("device", "device__user").get(
token_hash=DeviceSession.hash_token(raw_token)
)
except DeviceSession.DoesNotExist as exc:
raise DeviceSessionValidationError(
"device_session_invalid",
"设备会话无效或已过期",
) from exc
if not session.matches_token(raw_token) or not session.is_active_at():
raise DeviceSessionValidationError("device_session_invalid", "设备会话无效或已过期")
if session.device.status != ClientDevice.Status.ACTIVE:
raise DeviceSessionValidationError("device_revoked", "设备已被吊销")
if session.device.user_id != user.id:
raise DeviceSessionValidationError("device_mismatch", "设备会话不属于当前账号")
return session