diff --git a/backend/server/db/devices.ts b/backend/server/db/devices.ts index 3678c76..960f4a0 100644 --- a/backend/server/db/devices.ts +++ b/backend/server/db/devices.ts @@ -161,13 +161,25 @@ export async function registerDevice(opts: { return { device: created, created: true }; } -/** Touch lastSeenAt — wird in der Auth-Middleware bei jedem Request aufgerufen. */ -export async function touchDevice(userId: string, deviceId: string): Promise { +/** Touch lastSeenAt — wird in der Auth-Middleware bei jedem Request aufgerufen. + * Optional: backfillt name/model/osVersion wenn Headers da sind (für Devices + * die unter altem Build registriert wurden ohne diese Info). */ +export async function touchDevice( + userId: string, + deviceId: string, + info?: { name?: string | null; model?: string | null; osVersion?: string | null }, +): Promise { const db = usePrisma(); + const data: { lastSeenAt: Date; name?: string; model?: string; osVersion?: string } = { + lastSeenAt: new Date(), + }; + if (info?.name) data.name = info.name; + if (info?.model) data.model = info.model; + if (info?.osVersion) data.osVersion = info.osVersion; await db.userDevice .updateMany({ where: { userId, deviceId }, - data: { lastSeenAt: new Date() }, + data, }) .catch(() => { /* race-safe: wenn Device gerade gelöscht wurde */ diff --git a/backend/server/utils/auth.ts b/backend/server/utils/auth.ts index 39e5d9e..9f6d3c3 100644 --- a/backend/server/utils/auth.ts +++ b/backend/server/utils/auth.ts @@ -53,11 +53,26 @@ export async function requireUser( const deviceId = getHeader(event, 'x-device-id'); if (!deviceId) return user; + // Frontend sendet name/model/osVersion als x-device-* Headers (URL-encoded) + function readEncoded(name: string): string | null { + const raw = getHeader(event, name); + if (!raw) return null; + try { return decodeURIComponent(raw); } catch { return raw; } + } + const deviceName = readEncoded('x-device-name'); + const deviceModel = readEncoded('x-device-model'); + const deviceOs = readEncoded('x-device-os'); + const existing = await findUserDevice(user.id, deviceId); if (existing) { - // Touch lastSeenAt, throttled auf 1×/min — fire-and-forget + // Touch lastSeenAt + Backfill name/model/osVersion falls noch nicht gesetzt, + // throttled auf 1×/min — fire-and-forget if (Date.now() - existing.lastSeenAt.getTime() > TOUCH_THROTTLE_MS) { - touchDevice(user.id, deviceId).catch(() => {}); + touchDevice(user.id, deviceId, { + name: deviceName, + model: deviceModel, + osVersion: deviceOs, + }).catch(() => {}); } return user; } @@ -73,6 +88,9 @@ export async function requireUser( userId: user.id, deviceId, platform, + name: deviceName, + model: deviceModel, + osVersion: deviceOs, maxDevices: limits.maxAppDevices, }); return user;