From c1fd22af9b771f23cbd6170eb6dc62433cbf5c4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Valenta?= <git@imaniti.org> Date: Mon, 3 Apr 2023 23:35:32 +0200 Subject: [PATCH] add ClamAV support --- Dockerfile | 2 ++ .../0032_alter_signee_address_country.py | 19 ++++++++++++ contracts/models.py | 6 +++- env.example | 3 ++ registry/settings/base.py | 11 +++++-- requirements/base.txt | 1 + shared/middlewares.py | 31 +++++++++++++++++++ 7 files changed, 70 insertions(+), 3 deletions(-) create mode 100644 contracts/migrations/0032_alter_signee_address_country.py create mode 100644 shared/middlewares.py diff --git a/Dockerfile b/Dockerfile index ee761c2..8419d0d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,8 @@ RUN DATABASE_URL=postgres://x/x \ OIDC_RP_REALM_URL=x \ OIDC_RP_CLIENT_ID=x \ OIDC_RP_CLIENT_SECRET=x \ + CLAMD_TCP_SOCKET=x \ + CLAMD_TCP_ADDR=x \ DEFAULT_COUNTRY=x \ DEFAULT_CONTRACTEE_NAME=x \ DEFAULT_CONTRACTEE_STREET=x \ diff --git a/contracts/migrations/0032_alter_signee_address_country.py b/contracts/migrations/0032_alter_signee_address_country.py new file mode 100644 index 0000000..a4158bc --- /dev/null +++ b/contracts/migrations/0032_alter_signee_address_country.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.4 on 2023-04-03 21:35 + +import contracts.models +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('contracts', '0031_alter_contract_cost_unit_other_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='signee', + name='address_country', + field=models.CharField(blank=True, default=contracts.models.get_default_country, max_length=256, null=True, verbose_name='Země'), + ), + ] diff --git a/contracts/models.py b/contracts/models.py index 8fa16d2..ca97769 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -81,6 +81,10 @@ class RepresentativeMixin: return result +def get_default_country(): + return settings.DEFAULT_COUNTRY + + class Signee(CreatedByMixin, OwnPermissionsMixin, SignatureCountMixin, models.Model): name = models.CharField( max_length=256, @@ -129,7 +133,7 @@ class Signee(CreatedByMixin, OwnPermissionsMixin, SignatureCountMixin, models.Mo blank=True, null=True, verbose_name="Země", - default=settings.DEFAULT_COUNTRY, + default=get_default_country, ) ico_number = models.CharField( diff --git a/env.example b/env.example index 38e3261..797ac95 100644 --- a/env.example +++ b/env.example @@ -10,6 +10,9 @@ OIDC_RP_CLIENT_SECRET=VCn4LVAUc6RGLSup7VaAKsmrKUbWguaP DEFAULT_COUNTRY="Česká Republika" +CLAMD_TCP_SOCKET=3310 +CLAMD_TCP_ADDR=127.0.0.1 + DEFAULT_CONTRACTEE_NAME="Česká pirátská strana" DEFAULT_CONTRACTEE_STREET="Na Moráni 360/3" DEFAULT_CONTRACTEE_ZIP="128 00" diff --git a/registry/settings/base.py b/registry/settings/base.py index e4da047..380f476 100644 --- a/registry/settings/base.py +++ b/registry/settings/base.py @@ -70,14 +70,14 @@ INSTALLED_APPS = [ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", + "django.contrib.auth.middleware.AuthenticationMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", - "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", "django_http_exceptions.middleware.ExceptionHandlerMiddleware", "django_http_exceptions.middleware.ThreadLocalRequestMiddleware", - # "django_downloadview.SmartDownloadMiddleware", + "shared.middlewares.ClamAVMiddleware" ] ROOT_URLCONF = "registry.urls" @@ -216,6 +216,13 @@ ADMIN_ORDERING = { } +# ClamAV + +CLAMD_USE_TCP = True +CLAMD_TCP_SOCKET = env.int("CLAMD_TCP_SOCKET") +CLAMD_TCP_ADDR = env.str("CLAMD_TCP_ADDR") + + ## App-specific DEFAULT_CONTRACTEE_NAME = env.str("DEFAULT_CONTRACTEE_NAME") diff --git a/requirements/base.txt b/requirements/base.txt index dc65d55..d4143b6 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -1,3 +1,4 @@ +clamd==1.0.2 django==4.1.4 django-admin-index==2.0.2 django-admin-interface==0.24.2 diff --git a/shared/middlewares.py b/shared/middlewares.py new file mode 100644 index 0000000..bd3058c --- /dev/null +++ b/shared/middlewares.py @@ -0,0 +1,31 @@ +import clamd + +from io import BytesIO +from django.http import HttpResponseForbidden + +class ClamAVMiddleware: + def __init__(self, get_response): + self.get_response = get_response + # One-time configuration and initialization. + + def __call__(self, request): + # Code to be executed for each request before + # the view (and later middleware) are called. + + cd = clamd.ClamdUnixSocket() + + if request.method == "POST" and len(request.FILES) > 0: + for file_ in request.FILES.values(): + scan_result = cd.instream(BytesIO(file_.read())) + + if scan_result["stream"][0] == "FOUND": + return HttpResponseForbidden( + "Nahraný soubor obsahuje potenciálně škodlivý obsah." + ) + + response = self.get_response(request) + + # Code to be executed for each request/response after + # the view is called. + + return response -- GitLab