fix: block usr_ signups and improve runtime portability
This commit is contained in:
1 parent
8d42548c54
commit
7cc965ce52
1 file changed
+135
-36
+135
-36
@@ -4,6 +4,7 @@ import argparse
|
||||
import concurrent.futures
|
||||
import json
|
||||
import os
|
||||
import pwd
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -17,7 +18,7 @@ from pathlib import Path
|
||||
import dns.resolver
|
||||
|
||||
|
||||
VERSION = "6.1"
|
||||
VERSION = "6.5"
|
||||
|
||||
SOURCES = [
|
||||
"https://raw.githubusercontent.com/mehrtat/disposable-email-domain/main/domains.txt",
|
||||
@@ -25,8 +26,6 @@ SOURCES = [
|
||||
"https://disposable.github.io/disposable-email-domains/domains.txt",
|
||||
]
|
||||
|
||||
RUBY_BIN = "/home/mastodon/.rbenv/versions/3.4.7/bin"
|
||||
|
||||
DOMAIN_RE = re.compile(
|
||||
r"^(?=.{1,253}$)"
|
||||
r"(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+"
|
||||
@@ -169,28 +168,82 @@ def save_json_atomic(filename, value):
|
||||
os.unlink(temporary)
|
||||
|
||||
|
||||
def command_environment():
|
||||
def mastodon_owner(cwd):
|
||||
path = Path(cwd).resolve()
|
||||
stat = path.stat()
|
||||
account = pwd.getpwuid(stat.st_uid)
|
||||
|
||||
return {
|
||||
"uid": stat.st_uid,
|
||||
"gid": stat.st_gid,
|
||||
"name": account.pw_name,
|
||||
"home": Path(account.pw_dir),
|
||||
}
|
||||
|
||||
|
||||
def command_environment(cwd):
|
||||
env = os.environ.copy()
|
||||
owner = mastodon_owner(cwd)
|
||||
home = owner["home"]
|
||||
|
||||
env["PATH"] = (
|
||||
f"{RUBY_BIN}:"
|
||||
"/usr/local/bin:"
|
||||
"/usr/bin:"
|
||||
"/bin"
|
||||
)
|
||||
candidates = [
|
||||
home / ".rbenv" / "shims",
|
||||
home / ".rbenv" / "bin",
|
||||
home / ".asdf" / "shims",
|
||||
home / ".asdf" / "bin",
|
||||
home / ".local" / "share" / "mise" / "shims",
|
||||
home / ".local" / "bin",
|
||||
]
|
||||
|
||||
path_parts = []
|
||||
|
||||
for candidate in candidates:
|
||||
if candidate.is_dir():
|
||||
path_parts.append(str(candidate))
|
||||
|
||||
current_path = env.get("PATH", "")
|
||||
|
||||
if current_path:
|
||||
path_parts.append(current_path)
|
||||
|
||||
env["PATH"] = os.pathsep.join(path_parts)
|
||||
env["HOME"] = str(home)
|
||||
env["USER"] = owner["name"]
|
||||
env["LOGNAME"] = owner["name"]
|
||||
env["RAILS_ENV"] = "production"
|
||||
|
||||
rbenv_root = home / ".rbenv"
|
||||
|
||||
if rbenv_root.is_dir():
|
||||
env["RBENV_ROOT"] = str(rbenv_root)
|
||||
|
||||
return env
|
||||
|
||||
|
||||
def demote_to_mastodon_owner(cwd):
|
||||
owner = mastodon_owner(cwd)
|
||||
|
||||
if os.geteuid() != 0:
|
||||
return None
|
||||
|
||||
if owner["uid"] == 0:
|
||||
return None
|
||||
|
||||
def demote():
|
||||
os.initgroups(owner["name"], owner["gid"])
|
||||
os.setgid(owner["gid"])
|
||||
os.setuid(owner["uid"])
|
||||
|
||||
return demote
|
||||
|
||||
|
||||
def run_command(
|
||||
command,
|
||||
cwd,
|
||||
check=True,
|
||||
extra_env=None,
|
||||
):
|
||||
env = command_environment()
|
||||
env = command_environment(cwd)
|
||||
|
||||
if extra_env:
|
||||
env.update(extra_env)
|
||||
@@ -202,6 +255,7 @@ def run_command(
|
||||
text=True,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
preexec_fn=demote_to_mastodon_owner(cwd),
|
||||
)
|
||||
|
||||
if check and process.returncode != 0:
|
||||
@@ -225,7 +279,6 @@ def run_command(
|
||||
|
||||
return process
|
||||
|
||||
|
||||
def get_mastodon_blocks(mastodon_dir):
|
||||
ruby = r'''
|
||||
rows = EmailDomainBlock
|
||||
@@ -356,30 +409,40 @@ def cleanup_blocked_pending(
|
||||
dry_run=False,
|
||||
):
|
||||
|
||||
ruby = r'''
|
||||
dry_run = ENV["BLOCKER_DRY_RUN"] == "1"
|
||||
ruby = r'''dry_run = ENV["BLOCKER_DRY_RUN"] == "1"
|
||||
|
||||
checked = 0
|
||||
matched = 0
|
||||
matched_email = 0
|
||||
matched_username = 0
|
||||
deleted = 0
|
||||
errors = []
|
||||
|
||||
User
|
||||
.where(approved: false)
|
||||
.find_each(batch_size: 100) do |user|
|
||||
|
||||
next if user.email.blank?
|
||||
User.pending.find_each(batch_size: 100) do |user|
|
||||
next if user.account.nil?
|
||||
|
||||
checked += 1
|
||||
|
||||
begin
|
||||
next unless EmailDomainBlock.block?(user.email)
|
||||
blocked_email =
|
||||
user.email.present? &&
|
||||
EmailDomainBlock.block?(user.email)
|
||||
|
||||
blocked_username =
|
||||
user.account.username.to_s.match?(/\\Ausr_/i)
|
||||
|
||||
next unless blocked_email || blocked_username
|
||||
|
||||
matched += 1
|
||||
matched_email += 1 if blocked_email
|
||||
matched_username += 1 if blocked_username
|
||||
|
||||
reasons = []
|
||||
reasons << "email" if blocked_email
|
||||
reasons << "username" if blocked_username
|
||||
|
||||
if dry_run
|
||||
puts "__PENDING__#{user.id}\t#{user.email}"
|
||||
puts "__PENDING__#{user.id}\\t#{user.account.username}\\t#{reasons.join(",")}"
|
||||
next
|
||||
end
|
||||
|
||||
@@ -394,7 +457,7 @@ User
|
||||
rescue => e
|
||||
errors << {
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
username: user.account&.username,
|
||||
error: "#{e.class}: #{e.message}"
|
||||
}
|
||||
end
|
||||
@@ -404,6 +467,8 @@ STDOUT.write(
|
||||
"__CLEANUP__" + JSON.generate({
|
||||
checked: checked,
|
||||
matched: matched,
|
||||
matched_email: matched_email,
|
||||
matched_username: matched_username,
|
||||
deleted: deleted,
|
||||
errors: errors
|
||||
})
|
||||
@@ -457,7 +522,6 @@ STDOUT.write(
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def resolve_mx(
|
||||
domain,
|
||||
timeout,
|
||||
@@ -498,7 +562,7 @@ def main():
|
||||
"Disposable domains are hard-blocked; "
|
||||
"MX records are report-only; "
|
||||
"pending registrations using blocked "
|
||||
"email domains are removed."
|
||||
"email domains or usr_ usernames are removed."
|
||||
)
|
||||
)
|
||||
|
||||
@@ -573,7 +637,7 @@ def main():
|
||||
action="store_true",
|
||||
help=(
|
||||
"Do not remove pending registrations "
|
||||
"whose email is hard-blocked"
|
||||
"matched by email block or usr_ username"
|
||||
),
|
||||
)
|
||||
|
||||
@@ -583,15 +647,6 @@ def main():
|
||||
args.mastodon_dir
|
||||
)
|
||||
|
||||
ruby = Path(
|
||||
RUBY_BIN
|
||||
) / "ruby"
|
||||
|
||||
if not ruby.exists():
|
||||
raise SystemExit(
|
||||
f"Ruby non trovato: {ruby}"
|
||||
)
|
||||
|
||||
if not (
|
||||
mastodon_dir / "bin/rails"
|
||||
).exists():
|
||||
@@ -629,8 +684,23 @@ def main():
|
||||
f"{mastodon_dir}"
|
||||
)
|
||||
|
||||
owner = mastodon_owner(
|
||||
mastodon_dir
|
||||
)
|
||||
|
||||
log(
|
||||
f"[config] Ruby: {ruby}"
|
||||
f"[config] Utente Mastodon: "
|
||||
f"{owner['name']} "
|
||||
f"(uid={owner['uid']})"
|
||||
)
|
||||
|
||||
ruby_version = run_command(
|
||||
["ruby", "-v"],
|
||||
cwd=mastodon_dir,
|
||||
).stdout.strip()
|
||||
|
||||
log(
|
||||
f"[config] Ruby: {ruby_version}"
|
||||
)
|
||||
|
||||
log(
|
||||
@@ -822,6 +892,8 @@ def main():
|
||||
cleanup = {
|
||||
"checked": 0,
|
||||
"matched": 0,
|
||||
"matched_email": 0,
|
||||
"matched_username": 0,
|
||||
"deleted": 0,
|
||||
"errors": [],
|
||||
}
|
||||
@@ -848,6 +920,16 @@ def main():
|
||||
f"{cleanup['matched']:,}"
|
||||
)
|
||||
|
||||
log(
|
||||
f"[pending] per email : "
|
||||
f"{cleanup['matched_email']:,}"
|
||||
)
|
||||
|
||||
log(
|
||||
f"[pending] per usr_ : "
|
||||
f"{cleanup['matched_username']:,}"
|
||||
)
|
||||
|
||||
if args.dry_run:
|
||||
log(
|
||||
f"[pending] da eliminare: "
|
||||
@@ -873,7 +955,7 @@ def main():
|
||||
log(
|
||||
" "
|
||||
f"user={error['id']} "
|
||||
f"{error['email']} "
|
||||
f"{error.get('username', '')} "
|
||||
f"{error['error']}"
|
||||
)
|
||||
mx_to_domains = defaultdict(set)
|
||||
@@ -1069,6 +1151,12 @@ def main():
|
||||
"pending_blocked":
|
||||
cleanup["matched"],
|
||||
|
||||
"pending_matched_email":
|
||||
cleanup["matched_email"],
|
||||
|
||||
"pending_matched_username":
|
||||
cleanup["matched_username"],
|
||||
|
||||
"pending_deleted":
|
||||
cleanup["deleted"],
|
||||
|
||||
@@ -1180,6 +1268,16 @@ def main():
|
||||
f"{cleanup['matched']:,}"
|
||||
)
|
||||
|
||||
log(
|
||||
f" per email : "
|
||||
f"{cleanup['matched_email']:,}"
|
||||
)
|
||||
|
||||
log(
|
||||
f" per usr_ : "
|
||||
f"{cleanup['matched_username']:,}"
|
||||
)
|
||||
|
||||
log(
|
||||
f"Pending eliminati : "
|
||||
f"{cleanup['deleted']:,}"
|
||||
@@ -1232,3 +1330,4 @@ if __name__ == "__main__":
|
||||
log("ERRORE FATALE:")
|
||||
log(str(exc))
|
||||
raise
|
||||
|
||||
Reference in new issue
Block a user