]> git.ipfire.org Git - ipfire.org.git/commitdiff
dnsbl: Show the history of a list
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 31 Dec 2025 14:11:43 +0000 (14:11 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 31 Dec 2025 14:11:43 +0000 (14:11 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/backend/dnsbl.py
src/templates/dnsbl/lists/history.html [new file with mode: 0644]
src/templates/dnsbl/lists/show.html
src/web/__init__.py
src/web/dnsbl.py

index cde06b0074e0b7e303afc0eac3b7c6d06a320510..6839bfb536306a32ba28586385cc390aa7ed6de9 100644 (file)
@@ -190,6 +190,7 @@ templates_dnsbl_DATA = \
 templates_dnsbldir = $(templatesdir)/dnsbl
 
 templates_dnsbl_lists_DATA = \
+       src/templates/dnsbl/lists/history.html \
        src/templates/dnsbl/lists/index.html \
        src/templates/dnsbl/lists/reports.html \
        src/templates/dnsbl/lists/sources.html \
index 18329d0a6424a5e1a9262a2865d74832bd7665c2..62bb52135a6f3c66a53e400ef49756451e985cec 100644 (file)
@@ -6,6 +6,7 @@ import json
 import logging
 import pydantic
 import tornado.httpclient
+import typing
 import urllib.parse
 import uuid
 
@@ -239,6 +240,18 @@ class List(Model):
                # Return the report
                return Report(self._backend, **response)
 
+       # History
+
+       async def get_history(self, limit=None):
+               """
+                       Fetches the history of this list
+               """
+               response = await self._backend.dnsbl._fetch(
+                       "/lists/%s/history" % self.slug, args={ "limit" : limit },
+               )
+
+               return [History(self._backend, **data) for data in response]
+
 
 class Source(Model):
        """
@@ -331,3 +344,17 @@ class Report(Model):
                        self._list = await self._backend.dnsbl.get_list(self.list_slug)
 
                return self._list
+
+
+class History(Model):
+       """
+               Represents a history event
+       """
+       # Timestamp
+       ts: datetime.datetime
+
+       # Domains Added
+       domains_added: typing.List[str] = []
+
+       # Domains Removed
+       domains_removed: typing.List[str] = []
diff --git a/src/templates/dnsbl/lists/history.html b/src/templates/dnsbl/lists/history.html
new file mode 100644 (file)
index 0000000..e77ce5b
--- /dev/null
@@ -0,0 +1,90 @@
+{% extends "../../base.html" %}
+
+{% block head %}
+       {% module OpenGraph(
+               title=_("IPFire DNSBL - %s - History") % list,
+               description=list.description,
+       ) %}
+{% end block %}
+
+{% block title %}{{ _("IPFire DNSBL") }} - {{ list }} - {{ _("History") }}{% end block %}
+
+{% block container %}
+       <section class="hero is-dark">
+               <div class="hero-body">
+                       <div class="container">
+                               <nav class="breadcrumb" aria-label="breadcrumbs">
+                                       <ul>
+                                               <li>
+                                                       <a href="/dnsbl">
+                                                               {{ _("IPFire DNSBL") }}
+                                                       </a>
+                                               </li>
+
+                                               <li>
+                                                       <a href="/dnsbl/lists">
+                                                               {{ _("Lists") }}
+                                                       </a>
+                                               </li>
+
+                                               <li>
+                                                       <a href="/dnsbl/lists/{{ list.slug }}">
+                                                               {{ list }}
+                                                       </a>
+                                               </li>
+
+                                               <li class="is-active">
+                                                       <a href="#" aria-current="page">{{ _("History") }}</a>
+                                               </li>
+                                       </ul>
+                               </nav>
+
+                               <h1 class="title">
+                                       {{ _("History: %s") % list }}
+                               </h1>
+                       </div>
+               </div>
+       </section>
+
+       {# Events #}
+       {% for event in reversed(history) %}
+               <section class="section">
+                       <div class="container">
+                               <h5 class="title is-5">
+                                       {{ locale.format_date(event.ts) }}
+                               </h5>
+
+                               {# Tags #}
+                               <span class="tags">
+                                       {% if event.domains_added %}
+                                               <span class="tag is-success">
+                                                       &plus; {{ len(event.domains_added) }}
+                                               </span>
+                                       {% end %}
+
+                                       {% if event.domains_removed %}
+                                               <span class="tag is-danger">
+                                                       &minus; {{ len(event.domains_removed) }}
+                                               </span>
+                                       {% end %}
+                               </span>
+
+                               <ul>
+                                       {# Domains Added #}
+                                       {% for domain in event.domains_added %}
+                                               <li class="has-text-success">
+                                                       &plus; {{ domain }}
+                                               </li>
+                                       {% end %}
+
+                                       {# Domains Removed #}
+                                       {% for domain in event.domains_removed %}
+                                               <li class="has-text-danger">
+                                                       &minus; {{ domain }}
+                                               </li>
+                                       {% end %}
+                               </ul>
+                       </div>
+               </section>
+       {% end %}
+{% end block %}
index 2d3a144e8836b66fd6c76e704f31a3bf9892a55b..85d7b299f7fd433837559a8353a8a1a42b931447 100644 (file)
 
                                <a class="button" href="/dnsbl/lists/{{ list.slug }}/sources">
                                        <span class="icon is-small">
-                                               <i class="fas fa-list-check" aria-hidden="true"></i>
+                                               <i class="fas fa-code-pull-request" aria-hidden="true"></i>
                                        </span>
 
                                        <span>{{ _("Sources") }}</span>
                                </a>
+
+                               <a class="button" href="/dnsbl/lists/{{ list.slug }}/history">
+                                       <span class="icon is-small">
+                                               <i class="fas fa-list-check" aria-hidden="true"></i>
+                                       </span>
+
+                                       <span>{{ _("History") }}</span>
+                               </a>
                        </div>
                </div>
        </section>
index 1e1e440fb9fbcbcdbf8241b2bad5847ac8239664..92fe0fb5d34c0ebcd9512f556e69bd265d2a2041 100644 (file)
@@ -217,6 +217,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+)/history", dnsbl.ListHistoryHandler),
                        (r"/dnsbl/lists/(\w+)/reports", dnsbl.ListReportsHandler),
                        (r"/dnsbl/lists/(\w+)/sources", dnsbl.ListSourcesHandler),
                        (r"/dnsbl/report", dnsbl.SubmitReportHandler),
index 22a2249001305172ce129dcefceb0fba81db628a..58360111fddbc7a7e3a97640fbe70c68b001dbb8 100644 (file)
@@ -32,6 +32,20 @@ class ListHandler(base.AnalyticsMixin, BaseHandler):
                self.render("dnsbl/lists/show.html", list=list)
 
 
+class ListHistoryHandler(base.AnalyticsMixin, BaseHandler):
+       async def get(self, slug):
+               # 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 history
+               history = await list.get_history(limit=10)
+
+               # Render the page
+               self.render("dnsbl/lists/history.html", list=list, history=history)
+
+
 class ListReportsHandler(base.AnalyticsMixin, BaseHandler):
        async def get(self, slug):
                # Fetch the list