Bonjour tout le monde,
Sentry nous rapporte qu’un membre a souhaité réinitialiser son mot de passe à l’aide de son adresse mail, mais la ligne
usr = get_object_or_404(User, Q(email=email))
a soulevé l’erreur User.MultipleObjectsReturned get() returned more than one User -- it returned 2!
.
En faisant quelques statistiques sur la base de données, je me suis rendu compte qu’on a 56 adresses mail qui sont utilisées par deux comptes différents.
Quand on regarde à quels comptes sont associés ces adresses mail dupliquées, on se rend compte de plusieurs choses :
- la majorité des comptes sont actifs (ils ont validé l’adresse mail)
- la dernière inscription d’un membre avec une adresse mail déjà existante en base de données date d’octobre 2018, donc on peut estimer que c’est le moment où la vérification de l’adresse mail déjà existante a été ajoutée (j’ai vérifié, sur la version actuelle on ne peut pas s’inscrire deux fois avec la même adresse)
- la dernière connexion d’un membre qui a deux comptes avec la même adresse date du 30 septembre 2023.
Ma question est : que fait-on ? On a deux problèmes :
- les données dans la base ne sont pas cohérentes : les adresses mails devraient être uniques, or ce n’est pas le cas
- les membres qui ont deux comptes avec la même adresse mail ne peuvent pas demander un nouveau mot de passe s’ils choisissent de réinitialiser leur mot de passe en fournissant l’adresse mail (on peut aussi fournir le pseudo).
On pourrait :
- contacter toutes les adresses mails dupliquées pour demander quel compte il faut garder (mais les personnes risquent de ne pas répondre)
- gérer l’erreur du
get()
qui renvoie plusieurs résultats en invitant à contacter l’équipe technique (c’est probablement le plus facile, mais ça me semble être un patch pas très beau…) - d’autres idées ?
Les requêtes SQL utilisées
Liste des adresses mail dupliquées :
SELECT email, COUNT(email) AS nb FROM auth_user WHERE email != "" GROUP BY email HAVING nb>1;
Pour en savoir plus sur les membres concernés par les adresses dupliquées :
SELECT a.username, a.email, a.date_joined, a.last_login, a.is_active
FROM auth_user a
INNER JOIN (SELECT email FROM auth_user WHERE email != "" GROUP BY email HAVING COUNT(email)>1) b
ON a.email = b.email
ORDER BY last_login;
Les adresses mail vides correspondent aux connexions via Google ou Facebook.