Skip to content

Auto-ban duplicate users when a user is banned

Ian Anderson requested to merge ia-auto-ban-users-via-detumbled-email into master

What does this MR do and why?

Related to https://gitlab.com/gitlab-org/modelops/anti-abuse/team-tasks/-/issues/814

This MR implements the functionality when a user is banned to automatically ban other users that have the same detumbled email address. Email providers allow alternative addressing schemes that allow a user to modify their email address without changing the mailbox that the email is ultimately routed to. For example, user+123@gmail.com and user+456@gmail.com will both ultimately resolve to user@gmail.com.

Database changes

Change: Added Users.by_detumbled_emails scope

Single Detumbled Email

Raw SQL
SELECT "users".* FROM "users" 
INNER JOIN "emails" ON "emails"."user_id" = "users"."id" 
WHERE "emails"."detumbled_email" = 'user@gitlab.com'
Explain

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/31992/commands/98961

 Nested Loop  (cost=1.00..7.03 rows=1 width=1487) (actual time=0.050..0.072 rows=3 loops=1)
   Buffers: shared hit=19
   I/O Timings: read=0.000 write=0.000
   ->  Index Scan using index_emails_on_detumbled_email on public.emails  (cost=0.56..3.58 rows=1 width=4) (actual time=0.025..0.028 rows=3 loops=1)
         Index Cond: (emails.detumbled_email = 'user@gitlab.com'::text)
         Buffers: shared hit=7
         I/O Timings: read=0.000 write=0.000
   ->  Index Scan using users_pkey on public.users  (cost=0.44..3.46 rows=1 width=1487) (actual time=0.012..0.012 rows=1 loops=3)
         Index Cond: (users.id = emails.user_id)
         Buffers: shared hit=12
         I/O Timings: read=0.000 write=0.000

Multiple Detumbled Emails

Raw SQL
SELECT "users".* FROM "users" 
INNER JOIN "emails" ON "emails"."user_id" = "users"."id" 
WHERE "emails"."detumbled_email" IN ('user@gitlab.com', 'user@example.com')
Explain

https://postgres.ai/console/gitlab/gitlab-production-main/sessions/31992/commands/98959a

 Nested Loop  (cost=1.00..14.06 rows=2 width=1487) (actual time=12.729..28.820 rows=3 loops=1)
   Buffers: shared hit=8 read=18
   I/O Timings: read=28.478 write=0.000
   ->  Index Scan using index_emails_on_detumbled_email on public.emails  (cost=0.56..7.15 rows=2 width=4) (actual time=8.302..18.350 rows=3 loops=1)
         Index Cond: (emails.detumbled_email = ANY ('{user@gitlab.com,user@example.com}'::text[]))
         Buffers: shared hit=4 read=10
         I/O Timings: read=18.182 write=0.000
   ->  Index Scan using users_pkey on public.users  (cost=0.44..3.46 rows=1 width=1487) (actual time=3.476..3.476 rows=1 loops=3)
         Index Cond: (users.id = emails.user_id)
         Buffers: shared hit=4 read=8
         I/O Timings: read=10.296 write=0.000

MR acceptance checklist

Please evaluate this MR against the MR acceptance checklist. It helps you analyze changes to reduce risks in quality, performance, reliability, security, and maintainability.

Screenshots or screen recordings

Screenshots are required for UI changes, and strongly recommended for all other merge requests.

Before After

How to set up and validate locally

Numbered steps to set up and validate the change are strongly suggested.

Example below:

  1. In rails console enable the auto_ban_via_detumbled_email feature
    Feature.enable(:auto_ban_via_detumbled_email)
  2. Create a user with a tumbled email (i.e. user+1@example.com)
  3. Create another user with the same tumbled email (i.e. user+2@example.com).
  4. Ban one of the new users. The other user should be automatically banned as well.
  5. Retry the tests but add one of the users to a paid top-level namespace. When you ban the other user, the user in the paid namespace should be exempt from being auto-banned.
Edited by Ian Anderson

Merge request reports

Loading