109 lines
3.2 KiB
TypeScript
109 lines
3.2 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import { MemoryAuthStore } from "../src/stores/memory.ts";
|
|
import type { AuthIdentity, OAuthAccount, PasskeyCredential } from "../src/types.ts";
|
|
|
|
function identity(overrides: Partial<AuthIdentity> = {}): AuthIdentity {
|
|
return {
|
|
id: "identity-1",
|
|
userId: "user-1",
|
|
type: "email",
|
|
value: "first@example.com",
|
|
normalizedValue: "first@example.com",
|
|
primary: true,
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function passkey(overrides: Partial<PasskeyCredential> = {}): PasskeyCredential {
|
|
return {
|
|
id: "passkey-1",
|
|
userId: "user-1",
|
|
credentialId: "credential-1",
|
|
publicKey: "public-key",
|
|
counter: 0,
|
|
transports: ["internal"],
|
|
name: "Passkey",
|
|
createdAt: 1,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function oauth(overrides: Partial<OAuthAccount> = {}): OAuthAccount {
|
|
return {
|
|
id: "oauth-1",
|
|
userId: "user-1",
|
|
provider: "example",
|
|
providerAccountId: "provider-account-1",
|
|
createdAt: 1,
|
|
updatedAt: 1,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test("memory identity updates re-key lookups and reject collisions", async () => {
|
|
const store = new MemoryAuthStore();
|
|
const first = identity();
|
|
const second = identity({
|
|
id: "identity-2",
|
|
userId: "user-2",
|
|
value: "second@example.com",
|
|
normalizedValue: "second@example.com",
|
|
});
|
|
await store.createIdentity(first);
|
|
await store.createIdentity(second);
|
|
|
|
first.value = "renamed@example.com";
|
|
first.normalizedValue = "renamed@example.com";
|
|
first.updatedAt = 2;
|
|
await store.updateIdentity(first);
|
|
|
|
expect(await store.findIdentity("email", "first@example.com")).toBeUndefined();
|
|
expect(await store.findIdentity("email", "renamed@example.com")).toMatchObject({
|
|
id: "identity-1",
|
|
});
|
|
|
|
first.value = second.value;
|
|
first.normalizedValue = second.normalizedValue;
|
|
await expect(store.updateIdentity(first)).rejects.toThrow("WRN-AUTH-IDENTITY-EXISTS");
|
|
});
|
|
|
|
test("memory store enforces passkey credential uniqueness", async () => {
|
|
const store = new MemoryAuthStore();
|
|
await store.createPasskey(passkey());
|
|
await expect(
|
|
store.createPasskey(
|
|
passkey({ id: "passkey-2", userId: "user-2", credentialId: "credential-1" }),
|
|
),
|
|
).rejects.toThrow("WRN-AUTH-PASSKEY-EXISTS");
|
|
|
|
await store.createPasskey(
|
|
passkey({ id: "passkey-2", userId: "user-2", credentialId: "credential-2" }),
|
|
);
|
|
await expect(
|
|
store.updatePasskey(
|
|
passkey({ id: "passkey-2", userId: "user-2", credentialId: "credential-1" }),
|
|
),
|
|
).rejects.toThrow("WRN-AUTH-PASSKEY-IMMUTABLE");
|
|
});
|
|
|
|
test("memory store enforces OAuth provider-account uniqueness", async () => {
|
|
const store = new MemoryAuthStore();
|
|
await store.createOAuthAccount(oauth());
|
|
await expect(
|
|
store.createOAuthAccount(
|
|
oauth({ id: "oauth-2", userId: "user-2", providerAccountId: "provider-account-1" }),
|
|
),
|
|
).rejects.toThrow("WRN-AUTH-OAUTH-ACCOUNT-EXISTS");
|
|
|
|
await store.createOAuthAccount(
|
|
oauth({ id: "oauth-2", userId: "user-2", providerAccountId: "provider-account-2" }),
|
|
);
|
|
await expect(
|
|
store.updateOAuthAccount(
|
|
oauth({ id: "oauth-2", userId: "user-2", providerAccountId: "provider-account-1" }),
|
|
),
|
|
).rejects.toThrow("WRN-AUTH-OAUTH-ACCOUNT-IMMUTABLE");
|
|
});
|