mirror of
https://github.com/fromchat-messenger/web.git
synced 2026-09-22 19:15:08 +03:00
Restructure backend into microservices, add envelope encryption, DM files, and message editing
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List
|
||||
|
||||
from ..constants import OWNER_USERNAME
|
||||
from ..dependencies import get_current_user
|
||||
from ..models import User
|
||||
from ..security.audit import log_security
|
||||
from ..security.profanity import add_to_blocklist, get_blocklist, remove_from_blocklist
|
||||
from ..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"}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user