127 lines · 4.4 KB · TypeScript
RawDownload
import { expect, it } from "@effect/vitest";import * as DateTime from "effect/DateTime";import * as Effect from "effect/Effect";import * as Layer from "effect/Layer";import * as Option from "effect/Option"; import * as AuthConnectClients from "./AuthConnectClients.ts";import { SqlitePersistenceMemory } from "./Layers/Sqlite.ts"; const layer = AuthConnectClients.layer.pipe(Layer.provideMerge(SqlitePersistenceMemory)); const client = {  label: "Client",  ipAddress: null,  userAgent: null,  deviceType: "desktop",  os: "macOS",  browser: null,} satisfies AuthConnectClients.AuthConnectClientMetadataRecord; it.effect("clears stale last-seen timestamps when a revoked client re-registers", () =>  Effect.gen(function* () {    const clients = yield* AuthConnectClients.AuthConnectClientRepository;    const clientProofKeyThumbprint = "client-thumbprint";     yield* clients.upsertRequest({      clientProofKeyThumbprint,      cloudUserId: "cloud-user",      deviceId: "device-1",      client,      requestedAt: DateTime.makeUnsafe("2026-06-27T12:00:00.000Z"),    });    yield* clients.updateStatus({      clientProofKeyThumbprint,      status: "approved",      decidedAt: DateTime.makeUnsafe("2026-06-27T12:01:00.000Z"),    });    const seen = yield* clients.markSeen({      clientProofKeyThumbprint,      seenAt: DateTime.makeUnsafe("2026-06-27T12:02:00.000Z"),    });    expect(Option.isSome(seen) ? seen.value.lastSeenAt : null).not.toBeNull();     yield* clients.revoke({      clientProofKeyThumbprint,      revokedAt: DateTime.makeUnsafe("2026-06-27T12:03:00.000Z"),    });    const reregistered = yield* clients.upsertRequest({      clientProofKeyThumbprint,      cloudUserId: "cloud-user",      deviceId: "device-1",      client,      requestedAt: DateTime.makeUnsafe("2026-06-27T12:04:00.000Z"),    });     expect(reregistered.status).toBe("pending");    expect(reregistered.lastSeenAt).toBeNull();  }).pipe(Effect.provide(layer)),); it.effect("resets approval when the same proof key is requested by a different cloud user", () =>  Effect.gen(function* () {    const clients = yield* AuthConnectClients.AuthConnectClientRepository;    const clientProofKeyThumbprint = "client-thumbprint-cloud-user-change";     yield* clients.upsertRequest({      clientProofKeyThumbprint,      cloudUserId: "cloud-user-a",      deviceId: "device-1",      client,      requestedAt: DateTime.makeUnsafe("2026-06-27T13:00:00.000Z"),    });    yield* clients.updateStatus({      clientProofKeyThumbprint,      status: "approved",      decidedAt: DateTime.makeUnsafe("2026-06-27T13:01:00.000Z"),    });    yield* clients.markSeen({      clientProofKeyThumbprint,      seenAt: DateTime.makeUnsafe("2026-06-27T13:02:00.000Z"),    });     const reregistered = yield* clients.upsertRequest({      clientProofKeyThumbprint,      cloudUserId: "cloud-user-b",      deviceId: "device-1",      client,      requestedAt: DateTime.makeUnsafe("2026-06-27T13:03:00.000Z"),    });     expect(reregistered.cloudUserId).toBe("cloud-user-b");    expect(reregistered.status).toBe("pending");    expect(reregistered.approvedAt).toBeNull();    expect(reregistered.rejectedAt).toBeNull();    expect(reregistered.lastSeenAt).toBeNull();  }).pipe(Effect.provide(layer)),); it.effect("clears the opposite decision timestamp when approval status changes", () =>  Effect.gen(function* () {    const clients = yield* AuthConnectClients.AuthConnectClientRepository;    const clientProofKeyThumbprint = "client-thumbprint-status-flip";     yield* clients.upsertRequest({      clientProofKeyThumbprint,      cloudUserId: "cloud-user",      deviceId: "device-1",      client,      requestedAt: DateTime.makeUnsafe("2026-06-27T14:00:00.000Z"),    });    const rejected = yield* clients.updateStatus({      clientProofKeyThumbprint,      status: "rejected",      decidedAt: DateTime.makeUnsafe("2026-06-27T14:01:00.000Z"),    });    expect(Option.isSome(rejected) ? rejected.value.rejectedAt : null).not.toBeNull();    expect(Option.isSome(rejected) ? rejected.value.approvedAt : null).toBeNull();     const approved = yield* clients.updateStatus({      clientProofKeyThumbprint,      status: "approved",      decidedAt: DateTime.makeUnsafe("2026-06-27T14:02:00.000Z"),    });    expect(Option.isSome(approved) ? approved.value.approvedAt : null).not.toBeNull();    expect(Option.isSome(approved) ? approved.value.rejectedAt : null).toBeNull();  }).pipe(Effect.provide(layer)),);