Externen Zugriff Notfallhilfe eingerichtet, Sicherheitslücken geschlossen, Zeitabhängiger Login und Anzeige implementiert, Bereich 1 externer Zugriff fertig, Dokument-Download ohne Login aber mit zeitabhängig implementiert

This commit is contained in:
holger.trampe 2020-10-08 12:50:38 +02:00
parent 9db07bad2b
commit 1f72c65ccc
11 changed files with 873 additions and 12 deletions

View File

@ -5,7 +5,7 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
from users.views import AgencyCreateView, registerNewAgency from users.views import AgencyCreateView, registerNewAgency
from . import views from . import views
from .views import GetCryptFile from .views import GetCryptFile, GetCryptFileRecover
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from rest_framework.authtoken.views import obtain_auth_token from rest_framework.authtoken.views import obtain_auth_token
from django_encrypted_filefield.constants import FETCH_URL_NAME from django_encrypted_filefield.constants import FETCH_URL_NAME
@ -39,8 +39,10 @@ urlpatterns = [
path('api/', include('api.urls', namespace='api')), path('api/', include('api.urls', namespace='api')),
path('chat/', include('chat.urls'), name='chat'), path('chat/', include('chat.urls'), name='chat'),
path('api-token-auth/', obtain_auth_token, name='api-token-auth'), path('api-token-auth/', obtain_auth_token, name='api-token-auth'),
path('getdoc/<path:path>/<int:agpk>', GetCryptFileRecover.as_view(), name=FETCH_URL_NAME),
path('getdoc/<path:path>', GetCryptFile.as_view(), name=FETCH_URL_NAME), path('getdoc/<path:path>', GetCryptFile.as_view(), name=FETCH_URL_NAME),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG: if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@ -1,6 +1,6 @@
from django.shortcuts import render from django.shortcuts import render
from django.contrib.auth.mixins import AccessMixin 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 requests
import magic import magic
from django.conf import settings 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 import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import os, six import os, six
from recoverdir.models import RecoverDirSetting
from datetime import datetime
def _get_setting(name): def _get_setting(name):
setting_name = "DEFF_{}".format(name) setting_name = "DEFF_{}".format(name)
@ -60,6 +61,74 @@ def registerdone(request):
return render (request, 'users/registercomplete.html') 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): class GetCryptFile(DetailView):

View File

@ -26,6 +26,13 @@ class LoginRDForm(forms.Form):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields['pass'] = forms.CharField(widget=forms.PasswordInput, label="Passwort", required=True) 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 RecoverDirSettingForm(forms.ModelForm):
class Meta: class Meta:

View File

@ -23,7 +23,7 @@ class RecoverDirSetting(models.Model):
agency = models.ForeignKey(Agency, on_delete=models.CASCADE) agency = models.ForeignKey(Agency, on_delete=models.CASCADE)
logpass = encrypt(models.CharField(max_length=500, blank=True, default="", null=True)) logpass = encrypt(models.CharField(max_length=500, blank=True, default="", null=True))
recoverkey = 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. # Create your models here.
class PersLetter(models.Model): class PersLetter(models.Model):

View File

@ -0,0 +1,558 @@
{% extends "users/publicbase.html" %}
{% load crispy_forms_tags %}
{% block content %}
<style type="text/css">
.square_private_arrow {
float: right;
margin-right: 0px;
width: 65px;
height: 65px;
background-color: red;
color: #ffffff;
-webkit-clip-path:polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 25% 50%);
}
.square_company_arrow {
float: right;
margin-right: 0px;
width: 65px;
height: 65px;
background-color: black;
color: #ffffff;
-webkit-clip-path:polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 25% 50%);
}
.h2_in_arrow {
margin-left: 23px;
margin-top: 13px;
}
.tabelement {
}
</style>
<!-- CRISPY -->
<style type="text/css">
#logincard {
width: 80%;
margin-top: 2%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
<h2>Notfallhilfe für die Agentur {{agencydata.name}}
<a style="float: right" class="btn btn-secondary btn-sm mr-2 " href="{% url 'closeexternalrecoverdir' agencydata.pk %}"><i class="fas fa-lock"></i></a>
</h2>
<div id="accordion">
<!-- 1. NOTFALLLEITFADEN -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(1)" data-toggle="collapse" data-target="#rd_1" aria-expanded="true" aria-controls="rd_1">
<h4 style="margin-top: 11px;">1. Notfallleitfaden & Vorsorgedokumente</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#1</h2></span>
</span>
</h5>
</div>
<div id="rd_1" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
<a href="/#" data-toggle="modal" data-target="#hl">
<h4>Handlungsleitfaden betrachten</h4>
</a>
<hr>
<!-- HANDLUNGSLEITFADEN MODAL -->
<div class="modal fade" id="hl" tabindex="-1" role="dialog" aria-labelledby="hl_label" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Handlungsleitfen</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4>1. Bitte die zuständigen Regionaldirektion (RD) kontaktieren und um Hilfe bitten.</h4>
<table>
<tr>
<td>Zuständige RD</td>
<td>{{hl.rd_main|default:""}}</td>
</tr>
<tr>
<td>Name des RD-Leiters</td>
<td>{{hl.rd_prename|default:""}} {{hl.rd_postname|default:""}}</td>
</tr>
<tr>
<td>Straße RD</td>
<td>{{hl.rd_street|default:""}}</td>
</tr>
<tr>
<td>PLZ Ort</td>
<td>{{hl.rd_plz|default:""}} {{hl.rd_city|default:""}}</td>
</tr>
<tr>
<td>Telefon</td>
<td>{{hl.rd_tel|default:""}}</td>
</tr>
<tr>
<td>E-Mail</td>
<td>{{hl.rd_mail|default:""}}</td>
</tr>
</table>
<hr>
<h4>2. Kontaktiere bitte den Interessenverband VVE e.V. und bitte ihn um Hilfe.</h4>
<br />
<b>Geschäftstelle des VVE e.V.</b><br />
Verband der selbständigen Verischerungskaufleute er ERGO Gesellschaften e.V.<br />
Frankenthaler Str. 2<br />
68519 Viernheim<br /><br />
Telefon: 06204/964060<br />
E-Mail: geschaeftsstelle@myvve.de<br />
<hr>
<h4>3. Bitte beachte die nachfolgenden Unterlagen und Informationen innerhalb dieser Notfallhilfe. Hierbei handelt es sich um wichtige Unterlagen für den Notfall.</h4>
<hr>
<h4>4. Ich bin BVK Mitglied (Bundersverband Deutscher Versicherungskaufleute e.V.).</h4>
<br />
<p>Mitgliedsnummer: {{hl.bvk_number|default:""}}</p>
<b>Bundesverband Deutscher Versicherungskaufleute e.V.</b><br />
Kekuléstraße 12<br />
53115 Bonn<br /><br />
Telefon: 0228/22805-0<br />
E-Mail: bvk@bvk.de<br />
<hr>
<h4>5. Bei nachgelagerten Rechtsfragen wende Dich bitte an meinen Rechschutzversicherer.</h4>
<table>
<tr>
<td>Rechtsschutzversicherer</td>
<td>{{hl.rv_name|default:""}}</td>
</tr>
<tr>
<td>Versicherungsnummer</td>
<td>{{hl.rv_number|default:""}}</td>
</tr>
<tr>
<td>Telefon 1</td>
<td>{{hlvf.rv_tel_1|default:""}}</td>
</tr>
<tr>
<td>Telefon 2</td>
<td>{{hlvf.rv_tel_2|default:""}}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
<h4>Familie und Freunde
</h4>
<table class="table table-hover" id="a1_fc" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Beziehung</th>
<th scope="col">Adresse</th>
<th scope="col">Telefon</th>
</tr>
</thead>
<tbody >
{% for familyc in area_1_fc %}
<tr>
<td><a href="/#" data-toggle="modal" data-target="#familyc_{{familyc.pk}}">{{familyc.rd_prename|default:""}} {{familyc.rd_postname|default:""}}</a></td>
<td>{{familyc.rd_rel|default:""}}</td>
<td>{{familyc.rd_adresse|default:""}}</td>
<td>{{familyc.rd_tel|default:""}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h4>Vertrauensperson
</h4>
<table class="table table-hover" id="a1_trust" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Firma</th>
<th scope="col">Adresse</th>
<th scope="col">Telefon</th>
</tr>
</thead>
<tbody >
{% for trust in area_1_trust %}
<tr>
<td><a href="/#" data-toggle="modal" data-target="#trust_{{trust.pk}}">{{trust.rd_prename|default:""}} {{trust.rd_postname|default:""}}</a></td>
<td>{{trust.rd_company|default:""}}</td>
<td>{{trust.rd_adresse|default:""}}</td>
<td>{{trust.rd_tel|default:""}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h4>Vorsorgedokumente
</h4>
<table class="table table-hover" id="a1_docs" >
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Datum</th>
<th scope="col">Beschreibung</th>
<th scope="col">&nbsp;</th>
</tr>
</thead>
<tbody >
{% for doc in area_1_doc %}
<tr>
<td>{{doc.document_name|default:""}}</a></td>
<td>{{doc.document_date|date:"d.m.Y"|default:""}}</td>
<td>{{doc.document_desc|default:""}}</td>
<td><a href="{% url 'getdoc' doc.document agencydata.pk %}" target="_blank">Download</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% for familyc in area_1_fc %}
<!-- MODAL FAMILIEN UND FREUNDE -->
<div class="modal fade" id="familyc_{{familyc.pk}}" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Kontakt betrachten</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table>
<tr>
<td>Name:</td>
<td>{{familyc.rd_prename|default:""}} {{familyc.rd_postname|default:""}}</td>
</tr>
<tr>
<td>Beziehung:</td>
<td>{{familyc.rd_rel|default:""}}</td>
</tr>
<tr>
<td>Adresse:</td>
<td>{{familyc.rd_adresse|default:""}}</td>
</tr>
<tr>
<td>Telefonnummer:</td>
<td>{{familyc.rd_tel|default:""}}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- MODAL FÜR VERTRAUENSPERSONEN -->
{% for trust in area_1_trust %}
<div class="modal fade" id="trust_{{trust.pk}}" tabindex="-1" role="dialog" aria-labelledby="" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Vertraunsperson betrachten</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<table>
<tr>
<td>Name:</td>
<td>{{trust.rd_prename}} {{trust.rd_postname}}</td>
</tr>
<tr>
<td>Firma:</td>
<td>{{trust.rd_company}}</td>
</tr>
<tr>
<td>Adresse:</td>
<td>{{trust.rd_adresse}}</td>
</tr>
<tr>
<td>Telefonnummer:</td>
<td>{{trust.rd_tel}}</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">Schließen</button>
</div>
</div>
</div>
</div>
{% endfor %}
<!-- 2. ABSICHERUNG VERMÖGEN IMMOBILIEN -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(2)" data-toggle="collapse" data-target="#rd_2" aria-expanded="true" aria-controls="rd_2">
<h4 style="margin-top: 11px;">2. Absicherung, Vermögen & Immobilien</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#2</h2></span>
</span>
</h5>
</div>
<div id="rd_2" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 2
</div>
</div>
</div>
<!-- 3. Verträge -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(3)" data-toggle="collapse" data-target="#rd_3" aria-expanded="true" aria-controls="rd_3">
<h4 style="margin-top: 11px;">3. Verträge</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#3</h2></span>
</span>
</h5>
</div>
<div id="rd_3" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 3
</div>
</div>
</div>
<!-- 4. Digitale Konten -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(4)" data-toggle="collapse" data-target="#rd_4" aria-expanded="true" aria-controls="rd_4">
<h4 style="margin-top: 11px;">4. Digitale Konten & Passwörter</h4>
</button>
<span style="float: right;">
<span class="square_private_arrow"><h2 class="h2_in_arrow">#4</h2></span>
</span>
</h5>
</div>
<div id="rd_4" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 4
</div>
</div>
</div>
<!-- GEWERBE -->
<!-- 5. Vorsorgedokumente -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(5)" data-toggle="collapse" data-target="#rd_5" aria-expanded="true" aria-controls="rd_5">
<h4 style="margin-top: 11px;">5. Vorsorgedokumente</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#5</h2></span>
</span>
</h5>
</div>
<div id="rd_5" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 5
</div>
</div>
</div>
<!-- 6. Vorsroge und Finanzen -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(6)" data-toggle="collapse" data-target="#rd_6" aria-expanded="true" aria-controls="rd_6">
<h4 style="margin-top: 11px;">6. Vorsorge und Finanzen</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#6</h2></span>
</span>
</h5>
</div>
<div id="rd_6" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 6
</div>
</div>
</div>
<!-- 7. Immobilien -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(7)" data-toggle="collapse" data-target="#rd_7" aria-expanded="true" aria-controls="rd_7">
<h4 style="margin-top: 11px;">7. Immobilien</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#7</h2></span>
</span>
</h5>
</div>
<div id="rd_7" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 7
</div>
</div>
</div>
<!-- 8. Verträge -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(8)" data-toggle="collapse" data-target="#rd_8" aria-expanded="true" aria-controls="rd_8">
<h4 style="margin-top: 11px;">8. Verträge</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#8</h2></span>
</span>
</h5>
</div>
<div id="rd_8" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
ARA 8
</div>
</div>
</div>
<!-- 9. Sonstiges -->
<div class="card">
<div class="card-header" id="headingOne">
<h5 class="mb-0">
<button class="btn btn-link tabelement" onclick="javascript:newTabOpen(9)" data-toggle="collapse" data-target="#rd_9" aria-expanded="true" aria-controls="rd_9">
<h4 style="margin-top: 11px;">9. Sonstiges</h4>
</button>
<span style="float: right;">
<span class="square_company_arrow"><h2 class="h2_in_arrow">#9</h2></span>
</span>
</h5>
</div>
<div id="rd_9" class="collapse" aria-labelledby="headingOne" data-parent="#accordion">
<div class="card-body">
AREA 9
</div>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function(){
$('#a1_fc').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
$('#a1_trust').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
$('#a1_docs').DataTable({
"language": {
"search" : "Suche",
"info": "Zeige _START_ bis _END_ von _TOTAL_ Einträgen",
"lengthMenu": "Zeige _MENU_ Einträge",
"zeroRecords": "Nichts gefunden",
"infoEmpty": "Keine Einträge",
"paginate": {
"first": "Erste",
"last": "Letzte",
"next": "Nächste",
"previous": "Zurück"
},
},
"pageLength": 50,
"buttons" : {
"className" : "btn-danger"
}
});
})
</script>
{% endblock content %}

View File

@ -0,0 +1,44 @@
{% extends "users/publicbase.html" %}
<!-- CRISPY -->
{% load crispy_forms_tags %}
{% block content %}
<style type="text/css">
#logincard {
width: 25%;
margin-top: 7%;
}
</style>
<div class="card mx-auto" id="logincard">
<div class="card-body">
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert" id="message_{{forloop.counter}}">
{{ message }}
</div>
{% endfor %}
{% endif %}
<form method="POST">
{% csrf_token %}
<fieldset class="form-group" >
<legend class="border-bottom mb-4" style="text-align: center;">
<i class="fas fa-laptop"></i>
<h3>Digitale Agentur - Recover</h3>
</legend>
<p>Bitte geben Sie Passwort und Sicherheitsschlüssel ein! Es wird empfohlen, diese Seite <b><u>nur</u></b> im Inkognito-Modus aufzurufen! So verhinden Sie, dass Daten im Browser Zwischengespeichert werden!</p>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-primary">Notfallhilfe aufrufen</button>
</div>
</form>
</div>
</div>
<script type="text/javascript">
$("label[for*='username']").html("E-Mail-Adresse*");
$(document).ready(function(){
localStorage.clear();
})
</script>
{% endblock content %}

View File

@ -12,8 +12,9 @@ Permissions definiert in models.py bei USERS und dann hier vor die View geschrie
urlpatterns = [ urlpatterns = [
path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'), path('', permission_required('users.recoverdirmanager')(RecoverDirManagement.as_view(template_name="recoverdir/rd_management.html")), name='recoverdir'),
# RECOVER LINK EXTERN # 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/<int:agpk>', LoadExternalData.as_view(), name="load-rd-external-logged"),
path('recover/close/<int:agpk>', CloseExternalData.as_view(), name='closeexternalrecoverdir'),
# SETTINGS # SETTINGS
path('rdsettings/', permission_required('users.recoverdirmanager')(RecoverDirAddSettings.as_view()), name='recoverdir-addsettings'), path('rdsettings/', permission_required('users.recoverdirmanager')(RecoverDirAddSettings.as_view()), name='recoverdir-addsettings'),
path('rdsettings/update/<int:pk>', permission_required('users.recoverdirmanager')(RecoverDirUpdateSettings.as_view()), name='recoverdir-updatesettings'), path('rdsettings/update/<int:pk>', permission_required('users.recoverdirmanager')(RecoverDirUpdateSettings.as_view()), name='recoverdir-updatesettings'),

View File

@ -1,6 +1,6 @@
from django.shortcuts import render from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin 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 .models import *
from .forms import * from .forms import *
from django.urls import reverse_lazy from django.urls import reverse_lazy
@ -17,6 +17,7 @@ from itertools import chain
from django.contrib.auth.password_validation import * from django.contrib.auth.password_validation import *
from datetime import datetime from datetime import datetime
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
######## HELPER FUNCTIONS ######## HELPER FUNCTIONS
@ -52,9 +53,6 @@ def checkForLogin(self):
total_seconds = time_delta.total_seconds() total_seconds = time_delta.total_seconds()
minutes = total_seconds/60 minutes = total_seconds/60
print(userloginrdtime)
if(self.request.user.profile.rd_login == None or minutes > 30): if(self.request.user.profile.rd_login == None or minutes > 30):
self.request.user.profile.rd_login = None self.request.user.profile.rd_login = None
self.request.user.profile.save() self.request.user.profile.save()
@ -68,8 +66,175 @@ def checkForLogin(self):
############################################# EXTERNAL ACCESS ############################################ ############################################# EXTERNAL ACCESS ############################################
class LoadExternalDataLogin(FormView): 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 ############# VIEWS

View File

@ -62,7 +62,7 @@
.background-image { .background-image {
background-image: url('{% static 'users/img/registerbackground.jpg' %}'); background-image: url('{% static 'users/img/registerbackground.jpg' %}');
background-size: cover; /* Resize the background image to cover the entire container */ background-size: cover; /* Resize the background image to cover the entire container */
position: absolute; position: fixed;
left: 0; left: 0;
top: 0; top: 0;
width: 100%; width: 100%;
@ -102,5 +102,20 @@
{% block content %} {% block content %}
{% endblock %} {% endblock %}
<!-- Bootstrap core JavaScript-->
<!--<script src="{%static 'users/vendor/jquery/jquery.min.js' %}"></script>-->
<script type="text/javascript" src="{%static 'users/vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
<!-- Core plugin JavaScript-->
<script type="text/javascript" src="{%static 'users/vendor/jquery-easing/jquery.easing.min.js' %}"></script>
<!-- DATABLES JS -->
<!--<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/jquery.dataTables.min.js"></script>-->
<script type="text/javascript" src="{%static 'users/js/jquery_dataTables.min.js' %}"></script>
<!--<script type="text/javascript" src="https://cdn.datatables.net/1.10.20/js/dataTables.bootstrap4.min.js"></script>-->
<script type="text/javascript" src="{%static 'users/js/bs4_dt.js' %}"></script>
<!-- Custom scripts for all pages-->
<script type="text/javascript" src="{%static 'users/js/sb-admin-2.js' %}"></script>
</body> </body>
</html> </html>