from typing import Optional, TYPE_CHECKING from django.utils import timezone import ipaddress from board.models import Ban, RangeBan if TYPE_CHECKING: from board.models import Board def get_client_ip(request): "Get the IP address of a client-side request. Shamelessly copy/pasted from StackOverflow." x_forwarded_for = request.META.get("HTTP_X_FORWARDED_FOR") if x_forwarded_for: ip = x_forwarded_for.split(",")[0] else: ip = request.META.get("REMOTE_ADDR") return ip def get_ip_bans(ip: str) -> list: bans = list(Ban.objects.filter(ip=ip)) ip_addr = ipaddress.ip_address(ip) for rangeban in RangeBan.objects.all(): start = ipaddress.ip_address(rangeban.start) end = ipaddress.ip_address(rangeban.end) if ip_addr.version != start.version or ip_addr.version != end.version: continue if start <= ip_addr <= end: # type: ignore bans += [rangeban] return bans def is_banned(ip: str, board: Optional["Board"]) -> bool: now = timezone.now() bans = [ban for ban in get_ip_bans(ip) if ban.board == board or not ban.board] if bans: active = [ban for ban in bans if ban.expires > now] expired = [ban for ban in bans if ban.expires <= now] # Delete expired bans for ban in expired: ban.delete() return bool(active) else: return False