From: Michael Tremer Date: Wed, 7 Jan 2026 17:07:55 +0000 (+0000) Subject: dnsbl: Create a page that shows the history of a domain on a list X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6cca2b9b11314a13d052b987f51d8836437ba5cb;p=ipfire.org.git dnsbl: Create a page that shows the history of a domain on a list Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 6839bfb5..a7507b0a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -190,6 +190,7 @@ templates_dnsbl_DATA = \ templates_dnsbldir = $(templatesdir)/dnsbl templates_dnsbl_lists_DATA = \ + src/templates/dnsbl/lists/domain.html \ src/templates/dnsbl/lists/history.html \ src/templates/dnsbl/lists/index.html \ src/templates/dnsbl/lists/reports.html \ diff --git a/src/backend/dnsbl.py b/src/backend/dnsbl.py index 0cbf230f..c07f7d0c 100644 --- a/src/backend/dnsbl.py +++ b/src/backend/dnsbl.py @@ -252,6 +252,16 @@ class List(Model): return [History(self._backend, **data) for data in response] + async def get_domain_history(self, name): + """ + Fetches the history of a specific domain on this list + """ + response = await self._backend.dnsbl._fetch( + "/lists/%s/domains/%s" % (self.slug, name), + ) + + return [DomainHistory(self._backend, **data) for data in response] + class Source(Model): """ @@ -364,3 +374,32 @@ class History(Model): # Domains Removed domains_removed: typing.List[str] = [] + + +class DomainHistory(Model): + # Name + name: str + + # Timestamp + timestamp: datetime.datetime + + # Type + type: str + + # Block? + block: bool = True + + # By + by: str | None = None + + # Source Name + source_name: str | None = None + + # Report ID + report_id: uuid.UUID | None = None + + # Blocks + blocks: int = 0 + + # Allows + allows: int = 0 diff --git a/src/templates/dnsbl/lists/domain.html b/src/templates/dnsbl/lists/domain.html new file mode 100644 index 00000000..c9cfa1d8 --- /dev/null +++ b/src/templates/dnsbl/lists/domain.html @@ -0,0 +1,148 @@ +{% extends "../../base.html" %} + +{% block head %} + {% module OpenGraph( + title=_("IPFire DNSBL - %(list)s - Domain %(domain)s") %\ + { "list" : list, "domain" : name }, + description=list.description, + ) %} +{% end block %} + +{% block title %} + {{ _("IPFire DNSBL") }} - {{ list }} - {{ _("Domain %s") % name }} +{% end block %} + +{% block container %} +
+
+
+ + +
+
+

+ {{ name }} +

+ +

+ {{ _("Listing on %s") % list }} +

+
+ +
+ {% for event in events %} + {# Allowed? #} + {% if event.allows %} + + {{ _("Allowed") }} + + + {# Blocked? #} + {% elif event.blocks %} + + {{ _("Blocked") }} + + + {# Not Listed #} + {% else %} + + {{ _("Not Listed") }} + + {% end %} + + {# Only use the latest result #} + {% break %} + + {# If there are no events, this has never been listed #} + {% else %} + + {{ _("Not Listed") }} + + {% end %} +
+
+
+
+
+ + {# History #} + {% if events %} +
+
+
+ {{ _("History") }} +
+ + + + {% for event in events %} + + {# Timestamp #} + + + {# What happened? #} + + + {# Show the current status #} + {% if event.allows %} + + {% elif event.blocks %} + + {% else %} + + {% end %} + + {% end %} + +
+ {{ locale.format_date(event.timestamp, shorter=True) }} + + {% if event.type == "added" %} + {% if event.block %} + {{ _("A block was added by %s") % (event.by or event.source_name) }} + {% else %} + {{ _("The domain was exempted by %s") % (event.by or event.source_name) }} + {% end %} + + {% elif event.type == "removed" %} + {% if event.block %} + {{ _("A block was lifted by %s") % (event.by or event.source_name) }} + {% else %} + {{ _("An exemption was removed by %s") % (event.by or event.source_name) }} + {% end %} + {% end %} + + {{ _("Allowed") }} + + {{ _("Blocked") }} + + {{ _("Not Listed") }} +
+
+
+ {% end %} +{% end block %} diff --git a/src/templates/dnsbl/lists/history.html b/src/templates/dnsbl/lists/history.html index 9a4cd87c..360e27a3 100644 --- a/src/templates/dnsbl/lists/history.html +++ b/src/templates/dnsbl/lists/history.html @@ -80,22 +80,28 @@ diff --git a/src/templates/dnsbl/search.html b/src/templates/dnsbl/search.html index fbb8ce52..3cd8ab8d 100644 --- a/src/templates/dnsbl/search.html +++ b/src/templates/dnsbl/search.html @@ -39,7 +39,9 @@ diff --git a/src/web/__init__.py b/src/web/__init__.py index 66a8df41..00db7fe5 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -219,6 +219,7 @@ class Application(tornado.web.Application): (r"/dnsbl/?", StaticHandler, { "template" : "dnsbl/index.html" }), (r"/dnsbl/lists", dnsbl.ListsHandler), (r"/dnsbl/lists/(\w+)", dnsbl.ListHandler), + (r"/dnsbl/lists/(\w+)/domains/(.*)", dnsbl.ListDomainHandler), (r"/dnsbl/lists/(\w+)/history", dnsbl.ListHistoryHandler), (r"/dnsbl/lists/(\w+)/reports", dnsbl.ListReportsHandler), (r"/dnsbl/lists/(\w+)/sources", dnsbl.ListSourcesHandler), diff --git a/src/web/dnsbl.py b/src/web/dnsbl.py index 3cbbe364..741ba1b5 100644 --- a/src/web/dnsbl.py +++ b/src/web/dnsbl.py @@ -77,6 +77,20 @@ class ListSourcesHandler(base.AnalyticsMixin, BaseHandler): self.render("dnsbl/lists/sources.html", list=list, sources=sources) +class ListDomainHandler(base.AnalyticsMixin, BaseHandler): + async def get(self, slug, name): + # Fetch the list + list = await self.backend.dnsbl.get_list(slug) + if not list: + raise tornado.web.HTTPError(404, "Could not find list '%s'" % slug) + + # Fetch the events + events = await list.get_domain_history(name) + + # Render the page + self.render("dnsbl/lists/domain.html", list=list, name=name, events=events) + + class SubmitReportHandler(base.AnalyticsMixin, BaseHandler): async def get(self): # Fetch all lists