sec: server-side email domain check + IP block on violations
Only @tutlot.com emails allowed for registration (checked server-side, invisible to frontend inspect). Wrong domain → scary message + IP violation tracked. 5 violations → IP permanently blocked from login and registration. Block screen with OK button on frontend. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
47b89ded8d
commit
0562cb4e47
8 changed files with 123 additions and 30 deletions
|
|
@ -84,6 +84,14 @@ async def init_db() -> None:
|
|||
ON registrations(email);
|
||||
CREATE INDEX IF NOT EXISTS idx_registrations_login
|
||||
ON registrations(login);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ip_blocks (
|
||||
ip TEXT NOT NULL PRIMARY KEY,
|
||||
violation_count INTEGER NOT NULL DEFAULT 0,
|
||||
is_blocked INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
blocked_at TEXT DEFAULT NULL
|
||||
);
|
||||
""")
|
||||
# Migrations for existing databases (silently ignore if columns already exist)
|
||||
for stmt in [
|
||||
|
|
@ -398,3 +406,36 @@ async def save_telegram_batch(
|
|||
)
|
||||
await conn.commit()
|
||||
return batch_id
|
||||
|
||||
|
||||
async def is_ip_blocked(ip: str) -> bool:
|
||||
async with _get_conn() as conn:
|
||||
async with conn.execute(
|
||||
"SELECT is_blocked FROM ip_blocks WHERE ip = ?", (ip,)
|
||||
) as cur:
|
||||
row = await cur.fetchone()
|
||||
return bool(row["is_blocked"]) if row else False
|
||||
|
||||
|
||||
async def record_ip_violation(ip: str) -> int:
|
||||
"""Increment violation count for IP. Returns new count. Blocks IP at threshold."""
|
||||
async with _get_conn() as conn:
|
||||
await conn.execute(
|
||||
"""
|
||||
INSERT INTO ip_blocks (ip, violation_count) VALUES (?, 1)
|
||||
ON CONFLICT(ip) DO UPDATE SET violation_count = violation_count + 1
|
||||
""",
|
||||
(ip,),
|
||||
)
|
||||
async with conn.execute(
|
||||
"SELECT violation_count FROM ip_blocks WHERE ip = ?", (ip,)
|
||||
) as cur:
|
||||
row = await cur.fetchone()
|
||||
count = row["violation_count"]
|
||||
if count >= 5:
|
||||
await conn.execute(
|
||||
"UPDATE ip_blocks SET is_blocked = 1, blocked_at = datetime('now') WHERE ip = ?",
|
||||
(ip,),
|
||||
)
|
||||
await conn.commit()
|
||||
return count
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue