Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/MIGRATIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,19 @@ vide : schéma de la version précédente, données de tous les âges et de tout
NULL, lignes antérieures aux hooks), puis la séquence de boot (`PrepareForAutoMigrate`,
AutoMigrate, couche SQL). Modèle : `backend/cmd/server/migration_0060_integration_test.go`.
Procédure de montée de version et de retour arrière associée : `docs/runbooks/migration-0060.md`.

**Adresses e-mail en double à la casse près** (`0068`, #876). `GetByEmail` compare
`LOWER(email)` depuis #688, et `idx_users_email_lower` sert cette recherche. L'index n'est pas
unique, parce que des comptes créés avant #687 peuvent exister en double à la casse près. Avant de
proposer une contrainte unique, lister ces doublons (lecture seule) :
```sql
SELECT LOWER(email) AS adresse, COUNT(*) AS comptes,
array_agg(email ORDER BY created_at) AS graphies
FROM users
WHERE deleted_at IS NULL
GROUP BY LOWER(email)
HAVING COUNT(*) > 1;
```
Sans ligne, la base est prête pour une contrainte unique. Sinon, la connexion atteint la ligne
écrite exactement comme saisie, puis la plus ancienne : fusionner ou renommer les doublons est une
décision de données, pas une migration.
1 change: 1 addition & 0 deletions migrations/0068_users_email_lower_index.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP INDEX IF EXISTS idx_users_email_lower;
22 changes: 22 additions & 0 deletions migrations/0068_users_email_lower_index.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
-- #876 — index the lookup login actually runs.
--
-- Since #688, GetByEmail matches LOWER(email) so the casing typed never decides
-- which account is reached. The unique index on users.email is on the raw
-- column and cannot serve that predicate, so every sign-in, sign-up, reset and
-- invitation scanned users.
--
-- Deliberately NOT unique: rows written before #687 may hold case-variant
-- duplicates, and a unique index would fail this migration, and the boot with
-- it, on such a database. docs/MIGRATIONS.md has the query that lists them.
--
-- users is created by AutoMigrate, which runs before this layer; the guard only
-- matters for a run against an empty database.

DO $$
BEGIN
IF to_regclass('users') IS NULL THEN
RETURN;
END IF;
CREATE INDEX IF NOT EXISTS idx_users_email_lower ON users (LOWER(email));
END
$$;
Loading