Lors de l’utilisation du plugin de gamification, des points sont attribués pour les invitations utilisées.
Ceci est facilement abusé en envoyant des invitations et en les utilisant avec un compte dupliqué (faux).
Lorsqu’un tel faux compte est supprimé par l’administrateur, le comportement du plugin de gamification (et du système d’invitation) dépend de la manière dont l’invitation a été envoyée.
Si l’invitation était liée à une adresse e-mail spécifique et que l’utilisateur est supprimé, alors les enregistrements invite et user_invite sont supprimés en dur (!). La prochaine fois que le job Sidekiq UpdateScoresFor* s’exécutera, le plugin de gamification déduira à nouveau les points attribués du score.
Si l’invitation n’était pas liée à une adresse e-mail spécifique et que l’utilisateur est supprimé, alors l’enregistrement invited_users sera supprimé, mais l’enregistrement invite restera. La valeur redemption_count ne sera pas diminuée. Cela a du sens d’un point de vue car l’utilisation de l’invitation a eu lieu, même si l’utilisateur a été supprimé par la suite. Mais le plugin de gamification utilise le redemption_count pour calculer le score, donc les points ne seront pas déduits.
En déboguant cela, j’ai également constaté que le job de score ne prendra en compte que les invitations datant de moins de 10 jours. Donc, si une invitation est utilisée après 11 jours, aucun point ne sera attribué. J’allais dire 'Je suppose qu’il doit regarder updated_at au lieu de created_at mais lorsque le nombre d’utilisations de l’invitation est augmenté, l’horodatage updated_at n’est pas modifié.
Est-ce que quelque chose comme ceci fonctionnerait mieux (ajusté pour correspondre au format de requête évaluable - c’est un test pour l’explorateur de données ) :
-- [params]
-- date :start_date
-- date :end_date
SELECT
invited_by_id AS user_id,
COUNT(*) AS user_invites,
COUNT(*) * 10 AS invite_score
FROM invited_users iu
JOIN invites i ON i.id = iu.invite_id
JOIN users u ON u.id = iu.user_id
WHERE iu.redeemed_at::date BETWEEN :start_date AND :end_date
AND iu.user_id <> i.invited_by_id
AND u.created_at > iu.redeemed_at
GROUP BY invited_by_id
ORDER BY user_invites DESC
Lorsqu’un utilisateur est supprimé, il est effacé de la table invited_users, il ne serait donc plus compté. Si la suppression a eu lieu dans les 10 jours, elle serait automatiquement corrigée, si plus longtemps, elle nécessiterait un rafraîchissement manuel du score.
L’utilisation de la date redeemed_at tiendrait compte des invitations créées il y a plus de 10 jours.
AND iu.user_id <> i.invited_by_id exclurait également les auto-invitations.
La jointure avec la table users et l’ajout de AND u.created_at > iu.redeemed_at excluraient également l’invitation d’utilisateurs existants.
Ce serait une bonne approche, sauf pour une chose :
Cela ne fonctionne pas bien. Parfois, l’utilisateur est créé légèrement avant que le rachat n’ait eu lieu. Aucune idée pourquoi. La plupart du temps, des dixièmes de seconde, mais j’en ai aussi trouvé quelques-uns de dizaines de secondes.
Testé sur une base de données réelle.
select
iu.redeemed_at iu_AS redeemed_at,
u.created_at AS u_created_at,
u.created_at > iu.redeemed_at AS u_created_gt_iu_redeemed
from invited_users iu
left join users u on u.id = iu.user_id
where iu.redeemed_at is not null
order by iu.id desc;
iu_redeemed_at | u_created_at | u_created_gt_iu_redeemed
----------------------------+----------------------------+--------------------------
2023-09-08 00:00:47.557057 | 2023-09-08 00:00:48.376446 | t
2023-08-25 20:09:03.486362 | 2023-08-25 20:09:03.201357 | f
2023-08-15 23:38:32.271709 | 2023-08-15 23:38:33.570299 | t
2023-08-14 10:44:34.19912 | 2023-08-14 10:44:35.429371 | t
2023-08-12 13:41:10.428013 | 2023-08-12 13:41:11.733973 | t
2023-07-31 17:58:13.511289 | 2023-07-31 17:57:50.427111 | f
2023-07-23 00:56:33.455185 | 2023-07-23 00:55:47.999263 | f
2023-07-19 08:42:44.908096 | 2023-07-19 08:42:46.040201 | t
2023-06-30 09:11:38.829692 | 2023-06-30 09:11:39.618586 | t
2023-06-30 08:37:02.322192 | 2023-06-30 08:37:03.133769 | t
2023-06-29 16:24:01.705616 | 2023-06-29 16:24:02.55067 | t
2023-06-29 12:53:33.245688 | 2023-06-29 12:53:34.067159 | t
Je trouve cela un peu trop de « magie noire » car nous ne savons pas ce qui cause le délai.
Je soupçonne que le délai est causé par une grosse file d’attente sidekiq ou quelque chose de similaire et bien que la majorité soit inférieure à une seconde, environ 3 % se situent dans la plage de 0:00:01 à 0:15:00 (une seconde à 15 minutes).
Et un demi pour cent est de l’ordre de plusieurs jours, ce qui semble être le genre d’abus que nous essayons d’empêcher. Donc, bien que cela soit efficace, cela ferait plus de mal que de bien en raison du nombre de faux positifs.