2022-06-24 16:53:01 -07:00
|
|
|
from typing import Optional, TYPE_CHECKING
|
2022-06-24 16:50:46 -07:00
|
|
|
from django.utils import timezone
|
2022-06-20 15:26:35 -07:00
|
|
|
import ipaddress
|
|
|
|
|
|
2022-06-24 16:50:46 -07:00
|
|
|
from board.models import Ban, RangeBan
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if TYPE_CHECKING:
|
|
|
|
|
from board.models import Board
|
|
|
|
|
|
2022-06-20 15:26:35 -07:00
|
|
|
|
|
|
|
|
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
|
2022-06-24 16:50:46 -07:00
|
|
|
|
|
|
|
|
|
2022-06-24 16:53:01 -07:00
|
|
|
def is_banned(ip: str, board: Optional["Board"]) -> bool:
|
2022-06-24 16:50:46 -07:00
|
|
|
now = timezone.now()
|
|
|
|
|
bans = [ban for ban in get_ip_bans(ip) if ban.board == board or not ban.board]
|
|
|
|
|
if bans:
|
2022-06-26 20:27:42 -07:00
|
|
|
active = [ban for ban in bans if not ban.expires or ban.expires > now]
|
|
|
|
|
expired = [ban for ban in bans if ban.expires and ban.expires <= now]
|
2022-06-24 16:50:46 -07:00
|
|
|
# Delete expired bans
|
|
|
|
|
for ban in expired:
|
|
|
|
|
ban.delete()
|
|
|
|
|
return bool(active)
|
|
|
|
|
else:
|
|
|
|
|
return False
|