app/commands/find_abuser_by_domain.py
Adrià Casajús 7a69458aab
Fixed count
2025-07-28 14:01:21 +02:00

95 lines
2.9 KiB
Python

import argparse
import sys
import time
from sqlalchemy import func
from app.abuser_audit_log_utils import emit_abuser_audit_log, AbuserAuditLogAction
from app.db import Session
from app.jobs.mark_abuser_job import MarkAbuserJob
from app.log import LOG
from app.models import User
parser = argparse.ArgumentParser(
prog="Disable abusers by mailbox domain",
description="Find abusers that created an account with domain and optionally disable them",
)
parser.add_argument(
"-s", "--start_user_id", default=0, type=int, help="Initial user_id"
)
parser.add_argument("-e", "--end_user_id", default=0, type=int, help="Last user_id")
parser.add_argument(
"-d",
"--domain",
required=True,
type=str,
help="Domain used to create the mailboxes",
)
parser.add_argument(
"-x",
"--disable",
default=False,
help="Whether to disable the users and mark as abusers",
action="store_true",
)
args = parser.parse_args()
domain = args.domain
if not domain:
LOG.i("No domain specified")
sys.exit(1)
disable = args.disable
user_id_start = args.start_user_id
max_user_id = args.end_user_id
if max_user_id == 0:
max_user_id = Session.query(func.max(User.id)).scalar()
LOG.i(f"Checking user {user_id_start} to {max_user_id}")
step = 10000
sql = """
SELECT u.id, u.email, min(m.email)
FROM users u
LEFT JOIN mailbox m ON u.id = m.user_id
WHERE u.id>=:start AND u.id < :end AND u.disabled = False AND (m.email LIKE '%' || :domain OR u.email LIKE '%' || :domain)
GROUP BY u.id, u.email
"""
updated = 0
start_time = time.time()
if disable:
LOG.i("Users will be marked as abusers and disabled!")
else:
LOG.i("Users will NOT be marked as abusers")
for batch_start in range(user_id_start, max_user_id, step):
rows = Session.execute(
sql,
{
"start": batch_start,
"end": batch_start + step,
"domain": domain,
},
)
for row in rows:
LOG.i(f"Found UserID: {row[0]} : {row[1]} / {row[2]}")
if disable:
abuse_user = User.get(row[0])
abuse_user.disabled = True
emit_abuser_audit_log(
user_id=abuse_user.id,
action=AbuserAuditLogAction.MarkAbuser,
message="Filled through find_abuser_by_domain script",
admin_id=None,
)
job = MarkAbuserJob(user=abuse_user).store_job_in_db()
LOG.i(f"Marked user {abuse_user} as abuser with job {job}")
Session.commit()
elapsed = time.time() - start_time
last_batch_id = batch_start + step
time_per_user = elapsed / (last_batch_id - batch_start)
remaining = max_user_id - last_batch_id
time_remaining = (max_user_id - last_batch_id) * time_per_user
hours_remaining = time_remaining / 3600.0
LOG.i(
f"User {batch_start}/{max_user_id} {updated} {hours_remaining:.2f}hrs remaining"
)