diff --git a/src/routes/api/v2/license/+server.ts b/src/routes/api/v2/license/+server.ts index 761aea5..b21644f 100644 --- a/src/routes/api/v2/license/+server.ts +++ b/src/routes/api/v2/license/+server.ts @@ -50,6 +50,17 @@ export const POST: RequestHandler = async ({ request }) => { throw error(400, 'key does not belong to specified user'); } + // Record that this active key was validated. A failure to record the + // timestamp should not fail an otherwise valid validation. + try { + await prisma.licenseKey.update({ + where: { id: storedKey.id }, + data: { lastValidatedAt: new Date() } + }); + } catch (err) { + console.error('Failed to record license key validation:', err); + } + return jsonOk( serializeLicense({ key: storedKey.key, diff --git a/src/routes/api/v2/license/server.spec.ts b/src/routes/api/v2/license/server.spec.ts index 3770aa4..3fde419 100644 --- a/src/routes/api/v2/license/server.spec.ts +++ b/src/routes/api/v2/license/server.spec.ts @@ -4,7 +4,7 @@ import { _clearRateLimits } from '$lib/server/v2-rate-limit'; vi.mock('$lib/db', () => ({ prisma: { - licenseKey: { findFirst: vi.fn() }, + licenseKey: { findFirst: vi.fn(), update: vi.fn() }, user: { findUnique: vi.fn() } } })); @@ -15,6 +15,7 @@ import { POST } from './+server'; type POSTEvent = Parameters[0]; const mockKeyFindFirst = prisma.licenseKey.findFirst as ReturnType; +const mockKeyUpdate = prisma.licenseKey.update as ReturnType; const mockUserFindUnique = prisma.user.findUnique as ReturnType; function licenseRequest(body: unknown): Request { @@ -66,6 +67,10 @@ describe('POST /api/v2/license', () => { email_address: 'user@example.com' }); expect(Object.keys(body)).not.toContain('subscription_level'); + expect(mockKeyUpdate).toHaveBeenCalledWith({ + where: { id: storedKey.id }, + data: { lastValidatedAt: expect.any(Date) } + }); }); it('rejects a missing license_key', async () => { @@ -104,6 +109,7 @@ describe('POST /api/v2/license', () => { 400, 'license key is not active' ); + expect(mockKeyUpdate).not.toHaveBeenCalled(); }); it('rejects a nonexistent user', async () => {