diff --git a/Dockerfile b/Dockerfile index ee761c23557dcc65ba1fa5ad42cc2f7232c842fe..8419d0d425fe819b22782049aa95c86f7ff66d05 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 0000000000000000000000000000000000000000..a4158bc3cca6dceb00864f692cd021dbadcb5de9 --- /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 8fa16d2950392aea239e8efebd343140e0e1e2d7..ca97769da3939c7dbd8d9236a14aa17c13ac5270 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 38e326158c3f703a3db62b30070ee5f73507e5e3..797ac95162181c06256e0ad1eb8ae301f29546c3 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 e4da047817f8374fa8f90347816e334394286302..380f476a8e3ddcd712b73117bcb3bc52b5d8a51c 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 dc65d55174714f9d285f0fede46f87f174af041d..d4143b6dc710f1364c1a0bf1afe16654745a2cee 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 0000000000000000000000000000000000000000..bd3058c82f059444c72cc01ec4dada9fc64d2108 --- /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