mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
115 lines
3.1 KiB
Python
115 lines
3.1 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from pydantic import BaseModel, Field
|
|
from typing import List
|
|
|
|
from backend.shared.constants import OWNER_USERNAME
|
|
from backend.shared.dependencies import get_current_user
|
|
from backend.shared.models import User
|
|
from backend.security.audit import log_security
|
|
from backend.security.profanity import add_to_blocklist, get_blocklist, remove_from_blocklist
|
|
from backend.security.rate_limit import reset_rate_limit_for_ip, clear_all_rate_limits
|
|
|
|
|
|
class BlocklistUpdateRequest(BaseModel):
|
|
words: List[str] = Field(default_factory=list, min_items=1)
|
|
|
|
|
|
class UnblockIPRequest(BaseModel):
|
|
ip: str = Field(..., min_length=1)
|
|
|
|
|
|
router = APIRouter(prefix="/moderation", tags=["moderation"])
|
|
|
|
|
|
def _ensure_owner(user: User) -> None:
|
|
if user.username != OWNER_USERNAME:
|
|
raise HTTPException(status_code=403, detail="Only owner can perform this action")
|
|
|
|
|
|
@router.get("/blocklist")
|
|
def list_blocklist(current_user: User = Depends(get_current_user)):
|
|
_ensure_owner(current_user)
|
|
return {"words": get_blocklist()}
|
|
|
|
|
|
@router.post("/blocklist")
|
|
def append_blocklist(
|
|
request: BlocklistUpdateRequest,
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
_ensure_owner(current_user)
|
|
added, updated = add_to_blocklist(request.words)
|
|
log_security(
|
|
"blocklist_add",
|
|
actor=current_user.username,
|
|
actor_id=current_user.id,
|
|
added=added,
|
|
)
|
|
return {"added": added, "words": updated}
|
|
|
|
|
|
@router.delete("/blocklist")
|
|
def delete_from_blocklist(
|
|
request: BlocklistUpdateRequest,
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
_ensure_owner(current_user)
|
|
removed, updated = remove_from_blocklist(request.words)
|
|
log_security(
|
|
"blocklist_remove",
|
|
actor=current_user.username,
|
|
actor_id=current_user.id,
|
|
removed=removed,
|
|
)
|
|
return {"removed": removed, "words": updated}
|
|
|
|
|
|
@router.post("/unblock-ip")
|
|
def unblock_ip(
|
|
request: UnblockIPRequest,
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Unblock an IP address from rate limiting."""
|
|
_ensure_owner(current_user)
|
|
ip = request.ip.strip()
|
|
|
|
if not ip:
|
|
raise HTTPException(status_code=400, detail="IP address is required")
|
|
|
|
cleared = reset_rate_limit_for_ip(ip)
|
|
|
|
log_security(
|
|
"rate_limit_unblock",
|
|
actor=current_user.username,
|
|
actor_id=current_user.id,
|
|
ip=ip,
|
|
success=cleared,
|
|
)
|
|
|
|
if cleared:
|
|
return {"status": "success", "message": f"Rate limit cleared for IP: {ip}"}
|
|
else:
|
|
return {"status": "success", "message": f"No rate limit entries found for IP: {ip}"}
|
|
|
|
|
|
@router.post("/clear-all-rate-limits")
|
|
def clear_all_rate_limits_endpoint(
|
|
current_user: User = Depends(get_current_user)
|
|
):
|
|
"""Clear all rate limit entries. Use with caution."""
|
|
_ensure_owner(current_user)
|
|
|
|
cleared = clear_all_rate_limits()
|
|
|
|
log_security(
|
|
"rate_limit_clear_all",
|
|
actor=current_user.username,
|
|
actor_id=current_user.id,
|
|
entries_cleared=cleared,
|
|
)
|
|
|
|
return {"status": "success", "message": f"Cleared {cleared} rate limit entries"}
|
|
|
|
|
|
|