From a712216970e17af88f06aa56b722184f3ec5ba70 Mon Sep 17 00:00:00 2001 From: "Danilo G. Baio" Date: Fri, 2 Oct 2020 23:30:52 -0300 Subject: [PATCH] Add Server Model * Server page for showing IPv4 and IPv6 connectivity * Management command `server_update`: Update DNS values of the pkg-fallout servers --- README.rst | 3 + changelog.rst | 8 ++ ports/management/commands/server_update.py | 91 ++++++++++++++++++++++ ports/migrations/0002_server.py | 22 ++++++ ports/models.py | 8 ++ ports/templates/ports/base.html | 3 + ports/templates/ports/server_list.html | 51 ++++++++++++ ports/urls.py | 1 + ports/views.py | 14 +++- requirements.txt | 1 + 10 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 ports/management/commands/server_update.py create mode 100644 ports/migrations/0002_server.py create mode 100644 ports/templates/ports/server_list.html diff --git a/README.rst b/README.rst index 77b6cf8..f66034a 100644 --- a/README.rst +++ b/README.rst @@ -116,3 +116,6 @@ Execution for keeping the database always updated: 30 10 * * * /portsfallout/scripts/cron-scrapy.sh today 30 18 * * * /portsfallout/scripts/cron-scrapy.sh today + # Update DNS values of the pkg-fallout servers + 45 3 * * * python manage.py server_update + diff --git a/changelog.rst b/changelog.rst index 34cf6d4..1d9adca 100644 --- a/changelog.rst +++ b/changelog.rst @@ -1,6 +1,14 @@ Changelog ========= +Unreleased +---------- + +* Add Server page for showing IPv4 and IPv6 connectivity +* Add management command `server_update`: + Update DNS values of the pkg-fallout servers + + Version 1.4.0 ------------- diff --git a/ports/management/commands/server_update.py b/ports/management/commands/server_update.py new file mode 100644 index 0000000..f8318d5 --- /dev/null +++ b/ports/management/commands/server_update.py @@ -0,0 +1,91 @@ +# Copyright (c) 2020 Danilo G. Baio +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +from django.core.management.base import BaseCommand, CommandError +from ports.models import Server, Fallout + +from django.utils import timezone as dtz + +import parser +import dns.resolver + + +class Command(BaseCommand): + help = 'Update DNS values of the pkg-fallout servers' + + def add_arguments(self, parser): + + parser.add_argument('period', + nargs='?', + type=int, + help='Query entries from the last X days (default: 90)',) + + def handle(self, *args, **options): + + if not options['period']: + period = 90 + else: + period = options['period'] + + period_date = dtz.make_aware(dtz.datetime.today() - dtz.timedelta(days=period)) + Servers = Fallout.objects.filter(date__gte=period_date).values('server').distinct().order_by('server') + + for srv in Servers: + if srv['server']: + self.stdout.write(f"{srv['server']}") + + try: + dns_v4 = dns.resolver.query(srv['server'], 'A') + except: + dns_v4 = False + + try: + dns_v6 = dns.resolver.query(srv['server'], 'AAAA') + except: + dns_v6 = False + + if dns_v4: + self.stdout.write(self.style.SUCCESS(' Has IPv4 address')) + else: + self.stdout.write(self.style.ERROR(' IPv4 address not found')) + + if dns_v6: + self.stdout.write(self.style.SUCCESS(' Has IPv6 address')) + else: + self.stdout.write(self.style.ERROR(' IPv6 address not found')) + + + try: + db_srv = Server.objects.get(name=srv['server']) + except: + db_srv = None + + if db_srv: + if db_srv.v4 != bool(dns_v4) or db_srv.v6 != bool(dns_v6): + db_srv.v4 = bool(dns_v4) + db_srv.v6 = bool(dns_v6) + db_srv.save() + else: + db_srv = Server.objects.get_or_create(name=srv['server'], + v4 = bool(dns_v4), + v6 = bool(dns_v6))[0] \ No newline at end of file diff --git a/ports/migrations/0002_server.py b/ports/migrations/0002_server.py new file mode 100644 index 0000000..b4f6740 --- /dev/null +++ b/ports/migrations/0002_server.py @@ -0,0 +1,22 @@ +# Generated by Django 3.1 on 2020-10-03 01:41 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('ports', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='Server', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=48, unique=True)), + ('v4', models.BooleanField(default=False)), + ('v6', models.BooleanField(default=False)), + ], + ), + ] diff --git a/ports/models.py b/ports/models.py index 8d67ab2..324c5ff 100644 --- a/ports/models.py +++ b/ports/models.py @@ -66,3 +66,11 @@ def __str__(self): # head-arm64-default | net/findomain return self.env + " | " + self.port.origin + +class Server(models.Model): + name = models.CharField(max_length=48, unique=True) + v4 = models.BooleanField(default=False) + v6 = models.BooleanField(default=False) + + def __str__(self): + return self.name diff --git a/ports/templates/ports/base.html b/ports/templates/ports/base.html index a51e31e..04976bb 100644 --- a/ports/templates/ports/base.html +++ b/ports/templates/ports/base.html @@ -26,6 +26,9 @@ + diff --git a/ports/templates/ports/server_list.html b/ports/templates/ports/server_list.html new file mode 100644 index 0000000..ec5c547 --- /dev/null +++ b/ports/templates/ports/server_list.html @@ -0,0 +1,51 @@ +{% extends "ports/base.html" %} +{% block title %}Server list{% endblock %} +{% load bootstrap_pagination %} +{% block body_block %} + +
+ +

Server List

+ + + + + + + + + + {% for server in server_list %} + + + + + {% endfor %} + +
serverconnectivity
{{ server.name }} + {% if server.v4 %} + IPv4 + {% else %} + IPv4 + {% endif %} + + {% if server.v6 %} + IPv6 + {% else %} + IPv6 + {% endif %} + +
+ +
+ {% bootstrap_paginate page_obj range=10 show_prev_next="true" show_first_last="true" centered="true" extra_pagination_classes="justify-content-center" %} +
+ +
+
+
+

Some servers have only IPv6 connectivity.

+
+
+ +{% endblock %} \ No newline at end of file diff --git a/ports/urls.py b/ports/urls.py index dd42752..29360b3 100644 --- a/ports/urls.py +++ b/ports/urls.py @@ -41,6 +41,7 @@ path('fallout//', views.FalloutDetailView.as_view(), name='fdetail'), path('port', views.PortListView.as_view(), name='list'), path('port//', views.PortDetailView.as_view(), name='detail'), + path('server', views.ServerListView.as_view(), name='server'), path('about', views.about, name='about'), path('api/', include(router.urls)), ] diff --git a/ports/views.py b/ports/views.py index 6f0401b..f4339a5 100644 --- a/ports/views.py +++ b/ports/views.py @@ -25,7 +25,7 @@ from django.views.generic import View, TemplateView, ListView, DetailView from django.db.models import Count, Q from django.db.models.functions import TruncDay -from ports.models import Port, Category, Fallout +from ports.models import Port, Category, Fallout, Server from ports.serializers import CategorySerializer, PortSerializer, FalloutSerializer from ports.utils import IsRegex from rest_framework import filters, viewsets @@ -174,6 +174,17 @@ def get_context_data(self, **kwargs): return context +class ServerListView(ListView): + paginate_by = 50 + model = Server + ordering = ['name'] + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['navbar_server'] = 'active' + return context + + def about(request): context_dict = {'navbar_about':'active'} return render(request, 'ports/about.html', context_dict) @@ -207,4 +218,3 @@ class FalloutViewSet(viewsets.ReadOnlyModelViewSet): filter_backends = (filters.SearchFilter,) queryset = Fallout.objects.all().order_by('-date') serializer_class = FalloutSerializer - diff --git a/requirements.txt b/requirements.txt index 152b1df..4a7d109 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ requests scrapy djangorestframework python-dateutil +dnspython