porchlight/tests/test_store/test_migrations.py
Johan Lundberg f03d509eb4
fix(security): enforce globally-unique WebAuthn credential_id
The webauthn_credentials primary key is (user_id, credential_id), which does
not stop the same credential_id from existing under two users. Usernameless
authentication looks up the credential by id alone, so a duplicate could
resolve to the wrong account. Add a unique index on credential_id (migration
003); duplicate registration now raises DuplicateError.

Refs: porchlight-as2

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05 13:51:09 +02:00

43 lines
1.6 KiB
Python

from pathlib import Path
import aiosqlite
from porchlight.store.sqlite.migrations import run_migrations
MIGRATIONS_DIR = (
Path(__file__).resolve().parent.parent.parent / "src" / "porchlight" / "store" / "sqlite" / "migrations"
)
async def test_run_migrations_applies_initial() -> None:
async with aiosqlite.connect(":memory:") as db:
await db.execute("PRAGMA foreign_keys=ON")
count = await run_migrations(db, MIGRATIONS_DIR)
assert count == 3
async with db.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='users'") as cursor:
row = await cursor.fetchone()
assert row is not None
async def test_run_migrations_skips_already_applied() -> None:
async with aiosqlite.connect(":memory:") as db:
await db.execute("PRAGMA foreign_keys=ON")
first_count = await run_migrations(db, MIGRATIONS_DIR)
second_count = await run_migrations(db, MIGRATIONS_DIR)
assert first_count == 3
assert second_count == 0
async def test_run_migrations_creates_all_tables() -> None:
async with aiosqlite.connect(":memory:") as db:
await db.execute("PRAGMA foreign_keys=ON")
await run_migrations(db, MIGRATIONS_DIR)
async with db.execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name") as cursor:
tables = [row[0] async for row in cursor]
assert "users" in tables
assert "user_groups" in tables
assert "webauthn_credentials" in tables
assert "password_credentials" in tables
assert "magic_links" in tables
assert "user_consents" in tables
assert "_migrations" in tables