diff --git a/digitaleagentur/__pycache__/urls.cpython-38.pyc b/digitaleagentur/__pycache__/urls.cpython-38.pyc index d1deb75..7f386bd 100644 Binary files a/digitaleagentur/__pycache__/urls.cpython-38.pyc and b/digitaleagentur/__pycache__/urls.cpython-38.pyc differ diff --git a/digitaleagentur/__pycache__/views.cpython-38.pyc b/digitaleagentur/__pycache__/views.cpython-38.pyc index a8d9815..2f3e84e 100644 Binary files a/digitaleagentur/__pycache__/views.cpython-38.pyc and b/digitaleagentur/__pycache__/views.cpython-38.pyc differ diff --git a/digitaleagentur/urls.py b/digitaleagentur/urls.py index 2ae371b..bb0eec8 100644 --- a/digitaleagentur/urls.py +++ b/digitaleagentur/urls.py @@ -5,7 +5,7 @@ from django.conf import settings from django.conf.urls.static import static from users.views import AgencyCreateView, registerNewAgency from . import views -from .views import GetCryptFile +from .views import GetCryptFile, GetCryptFileRecover from django.contrib.auth.decorators import login_required from rest_framework.authtoken.views import obtain_auth_token from django_encrypted_filefield.constants import FETCH_URL_NAME @@ -39,8 +39,10 @@ urlpatterns = [ path('api/', include('api.urls', namespace='api')), path('chat/', include('chat.urls'), name='chat'), path('api-token-auth/', obtain_auth_token, name='api-token-auth'), + path('getdoc//', GetCryptFileRecover.as_view(), name=FETCH_URL_NAME), path('getdoc/', GetCryptFile.as_view(), name=FETCH_URL_NAME), + ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/digitaleagentur/views.py b/digitaleagentur/views.py index 83565ff..014cdb3 100644 --- a/digitaleagentur/views.py +++ b/digitaleagentur/views.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.contrib.auth.mixins import AccessMixin -from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView +from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, TemplateView import requests import magic from django.conf import settings @@ -13,7 +13,8 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC import os, six - +from recoverdir.models import RecoverDirSetting +from datetime import datetime def _get_setting(name): setting_name = "DEFF_{}".format(name) @@ -60,6 +61,74 @@ def registerdone(request): return render (request, 'users/registercomplete.html') +# TASK: Hier den Abruf von Dokumenten bei eingeloggtem Recover-Datum weniger als 10 Minuten implementieren +class GetCryptFileRecover(TemplateView): + def get(self, request, *args, **kwargs): + print("HI!") + + try: + settings = RecoverDirSetting.objects.filter(agency_id=kwargs['agpk'])[0] + except IndexError: + messages.warning(self.request, f'Diese Agentur hat keine Notfallhilfe.') + return redirect('load-rd-external') + + if settings.lastlogg == None: + messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') + return redirect('load-rd-external') + else: + now = datetime.now() + time_delta = (now-settings.lastlogg) + total_seconds = time_delta.total_seconds() + minutes = total_seconds/60 + if(settings.lastlogg != None and minutes < 10): + # LOGIN OK AND LOGIN EARLIER THAN 10 MINUTES + path = kwargs.get("path") + + # No path? You're boned. Move along. + if not path: + raise Http404 + + if self._is_url(path): + content = requests.get(path, stream=True).raw.read() + + else: + # Normalise the path to strip out naughty attempts + #path = os.path.normpath(path).replace(settings.MEDIA_URL, settings.MEDIA_ROOT, 1) + path = "media/" + path + # Evil path request! + #if not path.startswith(settings.MEDIA_ROOT): + # print("404 startswith") + # raise Http404 + + # The file requested doesn't exist locally. A legit 404 + if not os.path.exists(path): + raise Http404 + + with open(path, "rb") as f: + content = f.read() + + content = Cryptographer.decrypted(content) + return HttpResponse(content, content_type=magic.Magic(mime=True).from_buffer(content)) + + else: + # LOGIN TO OLD - SET LASTLOGG TO NONE AND SEND MESSAGE + settings.lastlogg = None + settings.save() + messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') + return redirect('load-rd-external') + + @staticmethod + def _is_url(path): + try: + URLValidator()(path) + return True + except ValidationError: + return False + + + + + class GetCryptFile(DetailView): diff --git a/recoverdir/forms.py b/recoverdir/forms.py index 22c61aa..7c5fc38 100644 --- a/recoverdir/forms.py +++ b/recoverdir/forms.py @@ -26,6 +26,13 @@ class LoginRDForm(forms.Form): super().__init__(*args, **kwargs) self.fields['pass'] = forms.CharField(widget=forms.PasswordInput, label="Passwort", required=True) + +class LoginRDExternalForm(forms.Form): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields['key'] = forms.CharField(label="Sicherheitssschlüssel", required=True) + self.fields['pass'] = forms.CharField(widget=forms.PasswordInput, label="Passwort", required=True) + class RecoverDirSettingForm(forms.ModelForm): class Meta: diff --git a/recoverdir/models.py b/recoverdir/models.py index 82d0f77..e15c6dc 100644 --- a/recoverdir/models.py +++ b/recoverdir/models.py @@ -23,7 +23,7 @@ class RecoverDirSetting(models.Model): agency = models.ForeignKey(Agency, on_delete=models.CASCADE) logpass = encrypt(models.CharField(max_length=500, blank=True, default="", null=True)) recoverkey = encrypt(models.CharField(max_length=500, blank=True, default="", null=True)) - + lastlogg = models.DateTimeField(null=True, blank=True, default=None) # Create your models here. class PersLetter(models.Model): diff --git a/recoverdir/templates/recoverdir/rd_external.html b/recoverdir/templates/recoverdir/rd_external.html new file mode 100644 index 0000000..ddffc8f --- /dev/null +++ b/recoverdir/templates/recoverdir/rd_external.html @@ -0,0 +1,558 @@ +{% extends "users/publicbase.html" %} +{% load crispy_forms_tags %} +{% block content %} + + + + + + +
+
+

Notfallhilfe für die Agentur {{agencydata.name}} + +

+ + +
+ +
+
+
+ + +

#1

+
+
+
+ +
+
+ + +

Handlungsleitfaden betrachten

+
+
+ + + + +

Familie und Freunde +

+ + + + + + + + + + + {% for familyc in area_1_fc %} + + + + + + + {% endfor %} + +
NameBeziehungAdresseTelefon
{{familyc.rd_prename|default:""}} {{familyc.rd_postname|default:""}}{{familyc.rd_rel|default:""}}{{familyc.rd_adresse|default:""}}{{familyc.rd_tel|default:""}}
+ +
+

Vertrauensperson +

+ + + + + + + + + + + {% for trust in area_1_trust %} + + + + + + + {% endfor %} + +
NameFirmaAdresseTelefon
{{trust.rd_prename|default:""}} {{trust.rd_postname|default:""}}{{trust.rd_company|default:""}}{{trust.rd_adresse|default:""}}{{trust.rd_tel|default:""}}
+ + +
+

Vorsorgedokumente +

+ + + + + + + + + + + {% for doc in area_1_doc %} + + + + + + + {% endfor %} + +
NameDatumBeschreibung 
{{doc.document_name|default:""}}{{doc.document_date|date:"d.m.Y"|default:""}}{{doc.document_desc|default:""}}Download
+
+
+
+ +{% for familyc in area_1_fc %} + + +{% endfor %} + + +{% for trust in area_1_trust %} + +{% endfor %} + + +
+
+
+ + +

#2

+
+
+
+ +
+
+ AREA 2 +
+
+
+ + +
+
+
+ + +

#3

+
+
+
+ +
+
+ AREA 3 +
+
+
+ + +
+
+
+ + +

#4

+
+
+
+ +
+
+ AREA 4 +
+
+
+ + + + +
+
+
+ + +

#5

+
+
+
+ +
+
+ AREA 5 +
+
+
+ + +
+
+
+ + +

#6

+
+
+
+ +
+
+ AREA 6 +
+
+
+ + +
+
+
+ + +

#7

+
+
+
+ +
+
+ AREA 7 +
+
+
+ + +
+
+
+ + +

#8

+
+
+
+ +
+
+ ARA 8 +
+
+
+ + +
+
+
+ + +

#9

+
+
+
+ +
+
+ AREA 9 +
+
+
+
+
+
+ +{% endblock content %} \ No newline at end of file diff --git a/recoverdir/templates/recoverdir/rd_external_login.html b/recoverdir/templates/recoverdir/rd_external_login.html new file mode 100644 index 0000000..8398e88 --- /dev/null +++ b/recoverdir/templates/recoverdir/rd_external_login.html @@ -0,0 +1,44 @@ +{% extends "users/publicbase.html" %} + +{% load crispy_forms_tags %} +{% block content %} + +
+
+ {% if messages %} + {% for message in messages %} + + {% endfor %} + {% endif %} +
+ {% csrf_token %} +
+ + +

Digitale Agentur - Recover

+
+

Bitte geben Sie Passwort und Sicherheitsschlüssel ein! Es wird empfohlen, diese Seite nur im Inkognito-Modus aufzurufen! So verhinden Sie, dass Daten im Browser Zwischengespeichert werden!

+ {{ form|crispy }} +
+
+ + + +
+
+
+
+ +{% endblock content %} \ No newline at end of file diff --git a/recoverdir/urls.py b/recoverdir/urls.py index fe66a48..e1d111b 100644 --- a/recoverdir/urls.py +++ b/recoverdir/urls.py @@ -12,8 +12,9 @@ Permissions definiert in models.py bei USERS und dann hier vor die View geschrie urlpatterns = [ path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'), # RECOVER LINK EXTERN - path('recover/login/', LoadExternalDataLogin.as_view(), name="load-rd-external-login"), - + path('recover/', LoadExternalDataLogin.as_view(), name="load-rd-external"), + path('recover/lg/', LoadExternalData.as_view(), name="load-rd-external-logged"), + path('recover/close/', CloseExternalData.as_view(), name='closeexternalrecoverdir'), # SETTINGS path('rdsettings/', permission_required('users.recoverdirmanager')(RecoverDirAddSettings.as_view()), name='recoverdir-addsettings'), path('rdsettings/update/', permission_required('users.recoverdirmanager')(RecoverDirUpdateSettings.as_view()), name='recoverdir-updatesettings'), diff --git a/recoverdir/views.py b/recoverdir/views.py index 6637a4b..7d30949 100644 --- a/recoverdir/views.py +++ b/recoverdir/views.py @@ -1,6 +1,6 @@ from django.shortcuts import render from django.contrib.auth.mixins import LoginRequiredMixin -from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, FormView +from django.views.generic import CreateView, ListView, UpdateView, DetailView, DeleteView, FormView, TemplateView from .models import * from .forms import * from django.urls import reverse_lazy @@ -17,6 +17,7 @@ from itertools import chain from django.contrib.auth.password_validation import * from datetime import datetime from django.contrib.auth.models import User +from django.core.exceptions import ObjectDoesNotExist ######## HELPER FUNCTIONS @@ -52,9 +53,6 @@ def checkForLogin(self): total_seconds = time_delta.total_seconds() minutes = total_seconds/60 - - print(userloginrdtime) - if(self.request.user.profile.rd_login == None or minutes > 30): self.request.user.profile.rd_login = None self.request.user.profile.save() @@ -68,8 +66,175 @@ def checkForLogin(self): ############################################# EXTERNAL ACCESS ############################################ class LoadExternalDataLogin(FormView): - pass + template_name = "recoverdir/rd_external_login.html" + form_class = LoginRDExternalForm + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + return context + def form_valid(self, form): + key = form.cleaned_data.get("key") + password = form.cleaned_data.get("pass") + settings = RecoverDirSetting.objects.all() + + # LOGIN IN DIE NOTFALLHILFE + for ele in settings: + if(ele.recoverkey == key and ele.logpass == password): + ele.lastlogg = datetime.now() + ele.save() + return redirect('load-rd-external-logged', agpk=ele.agency.pk) + else: + messages.warning(self.request, f'Die eingegebenen Daten sind nicht korrekt!') + return redirect('load-rd-external') + return super().form_valid(form) + +class CloseExternalData(TemplateView): + template_name = "" + + + def dispatch(self, *arg, **kwargs): + try: + settings = RecoverDirSetting.objects.filter(agency_id=kwargs['agpk'])[0] + except IndexError: + messages.warning(self.request, f'Diese Agentur hat keine Notfallhilfe.') + return redirect('load-rd-external') + + settings.lastlogg = None + settings.save() + messages.warning(self.request, f'Externer Zugang erfolgreich geschlossen.') + return redirect('load-rd-external') + + +class LoadExternalData(TemplateView): + template_name = "recoverdir/rd_external.html" + context_object_name = 'agencydata' + + def dispatch(self, *args, **kwargs): + try: + settings = RecoverDirSetting.objects.filter(agency_id=kwargs['agpk'])[0] + except IndexError: + messages.warning(self.request, f'Diese Agentur hat keine Notfallhilfe.') + return redirect('load-rd-external') + + if settings.lastlogg == None: + messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') + return redirect('load-rd-external') + else: + now = datetime.now() + time_delta = (now-settings.lastlogg) + total_seconds = time_delta.total_seconds() + minutes = total_seconds/60 + if(settings.lastlogg != None and minutes < 10): + # LOGIN OK AND LOGIN EARLIER THAN 10 MINUTES + settings.lastlogg = datetime.now() + settings.save() + return super().dispatch(*args, **kwargs) + else: + # LOGIN TO OLD - SET LASTLOGG TO NONE AND SEND MESSAGE + settings.lastlogg = None + settings.save() + messages.warning(self.request, f'Bitte loggen Sie sich erneut ein!') + return redirect('load-rd-external') + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + agency = Agency.objects.get(pk=kwargs['agpk']) + + persletters = PersLetter.objects.filter(agency=agency) + handlungsleitfaden = Handlungsleitfaden.objects.filter(agency=agency) + contactfc = RDContact.objects.filter(agency=agency) + contactstrust = RDTrustPerson.objects.filter(agency=agency) + depistvollmacht = DepositVollmacht.objects.filter(agency=agency) + + # LOAD DATA + ergodigi = ErgoVerDir.objects.filter(agency=agency) + context.update({"area_2_ergo" : ergodigi}) + + onlinebank = OnlineBank.objects.filter(agency=agency, area=2) + context.update({"area_2_onlinebank" : onlinebank}) + + onlinebank6 = OnlineBank.objects.filter(agency=agency, area=6) + context.update({"area_6_onlinebank" : onlinebank6}) + + streamingabo = StreamingAbo.objects.filter(agency=agency) + context.update({"area_3_abos" : streamingabo}) + + digitalaccount = DigitalAccounts.objects.filter(agency=agency, area=4) + context.update({"area_4_digitalaccount" : digitalaccount}) + + digitalaccount8 = DigitalAccounts.objects.filter(agency=agency, area=8) + context.update({"area_8_digitalaccount" : digitalaccount8}) + + personal = Personal.objects.filter(agency=agency) + context.update({"area_5_personal" : personal}) + + rdcontract = RDContract.objects.filter(agency=agency) + context.update({"area_7_contract" : rdcontract}) + + elseele = RDElse.objects.filter(agency=agency) + context.update({"area_9_else" : elseele}) + + users_of_agency = User.objects.filter(profile__agency=agency) + context.update({"users_of_agency" : users_of_agency}) + + # Bereich 2 - Handlungsleitfaden FV ########## ########## ########## ########## ########## ########## + hlfv = HandlungsleitfadenVF.objects.filter(agency=agency) + if(len(hlfv) == 1): + hlfv = HandlungsleitfadenVF.objects.filter(agency=agency)[0] + else: + hlfv = None + context.update({'area_2_hlfv' : hlfv}) + + #Bankenvollmachten usw. + context.update({'area_2_deposit' : depistvollmacht}) + + # Bereich 1 - Handlungsleitfaden ########## ########## ########## ########## ########## ########## + # Handlungsleitfaden + hl = Handlungsleitfaden.objects.filter(agency=agency) + if(len(hl) == 1): + hl = Handlungsleitfaden.objects.filter(agency=agency)[0] + else: + hl = None + + context.update({'hl' : hl}) + + # Familien-Freunde + context.update({'area_1_fc' : RDContact.objects.filter(agency=agency)}) + + # Vertrauensperson + context.update({'area_1_trust' : RDTrustPerson.objects.filter(agency=agency)}) + + # Dokumente + # A1 + context.update({'area_1_doc' : Documents.objects.filter(agency=agency, area=1).order_by('-document_date')}) + # A2 + context.update({'area_2_doc' : Documents.objects.filter(agency=agency, area=2).order_by('-document_date')}) + # A3 + context.update({'area_3_doc' : Documents.objects.filter(agency=agency, area=3).order_by('-document_date')}) + + # A4 + context.update({'area_4_doc' : Documents.objects.filter(agency=agency, area=4).order_by('-document_date')}) + + # A5 + context.update({'area_5_doc' : Documents.objects.filter(agency=agency, area=5).order_by('-document_date')}) + + # A6 + context.update({'area_6_doc' : Documents.objects.filter(agency=agency, area=6).order_by('-document_date')}) + + # A7 + context.update({'area_7_doc' : Documents.objects.filter(agency=agency, area=7).order_by('-document_date')}) + + # A8 + context.update({'area_8_doc' : Documents.objects.filter(agency=agency, area=8).order_by('-document_date')}) + + # A9 + context.update({'area_9_doc' : Documents.objects.filter(agency=agency, area=9).order_by('-document_date')}) + + context.update({ + 'agencydata' : agency, + }) + return context ############# VIEWS diff --git a/users/templates/users/publicbase.html b/users/templates/users/publicbase.html index c1cd9ed..88cd539 100644 --- a/users/templates/users/publicbase.html +++ b/users/templates/users/publicbase.html @@ -62,7 +62,7 @@ .background-image { background-image: url('{% static 'users/img/registerbackground.jpg' %}'); background-size: cover; /* Resize the background image to cover the entire container */ - position: absolute; + position: fixed; left: 0; top: 0; width: 100%; @@ -102,5 +102,20 @@ {% block content %} {% endblock %} + + + + + + + + + + + + + + +