From 50798f2814f397fbdd85b70dabca9dfb26d4cd02 Mon Sep 17 00:00:00 2001 From: Andrea Lepori Date: Sun, 9 Aug 2020 18:19:11 +0200 Subject: comment code, minor bug fixes --- accounts/views.py | 43 ++++-- client/templates/client/approve.html | 6 + client/templates/client/index.html | 42 +++--- client/views.py | 83 ++++++++--- server/templates/server/doc_list.html | 9 ++ server/views.py | 250 +++++++++++++++++++++++++++------- 6 files changed, 340 insertions(+), 93 deletions(-) diff --git a/accounts/views.py b/accounts/views.py index 4dd69a4..50266b1 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -11,15 +11,18 @@ from django.http import HttpResponseRedirect from client.models import UserCode -import dateparser, os +import dateparser +import os from io import BytesIO from PIL import Image, UnidentifiedImageError @sensitive_variables("raw_passsword") def signup(request): + # signup form with terms if request.method == 'POST': if "terms_accept" not in request.POST: + # if terms not accepted return error and form again form = UserCreationForm() context = { "form": form, @@ -27,6 +30,7 @@ def signup(request): "error_text": "Accettare i termini e condizioni prego" } return render(request, 'accounts/signup.html', context) + # terms accepted create user in db form = UserCreationForm(request.POST) if form.is_valid(): form.save() @@ -35,8 +39,9 @@ def signup(request): user = authenticate(username=username, password=raw_password) login(request, user) return HttpResponseRedirect('/') - else: - form = UserCreationForm() + + # create empty form to be filled + form = UserCreationForm() context = { "form": form, } @@ -46,18 +51,25 @@ def signup(request): @login_required def personal(request): context = {} + # additional user informations usercode = UserCode.objects.filter(user=request.user)[0] + # medical info medic = usercode.medic + # values for multiple choice box + # TODO remove multiple choice branca_default = "" branca_castorini = "" branca_lupetti = "" branca_esploratori = "" branca_pionieri = "" branca_rover = "" + + # variables for throwing errors to the user error = False error_text = "" if request.method == "POST": + # requested download if request.POST['action'] == "download_vac": if medic.vac_certificate != None: filename = os.path.basename(medic.vac_certificate.name) @@ -76,6 +88,7 @@ def personal(request): filename = filename + ".jpg" return FileResponse(medic.health_care_certificate.file, as_attachment=True, filename=filename) + # set all attributes request.user.first_name = request.POST["first_name"] request.user.last_name = request.POST["last_name"] request.user.email = request.POST["email"] @@ -114,19 +127,22 @@ def personal(request): medic.misc = request.POST["misc"] medic.save() - #if "branca" in request.POST: + # if "branca" in request.POST: # if request.POST["branca"] != "": # request.user.groups.clear() # request.user.groups.add( # Group.objects.get(name=request.POST["branca"])) - + + # check if user uploaded a file if "vac_certificate" in request.FILES: myfile = request.FILES['vac_certificate'] try: im = Image.open(myfile) im_io = BytesIO() + # compress image in WEBP im.save(im_io, 'WEBP', quality=50) - medic.vac_certificate.save(request.user.username+"_"+myfile.name, im_io) + medic.vac_certificate.save( + request.user.username+"_"+myfile.name, im_io) medic.save() except UnidentifiedImageError: error = True @@ -137,14 +153,16 @@ def personal(request): try: im = Image.open(myfile) im_io = BytesIO() + # compress image in WEBP im.save(im_io, 'WEBP', quality=50) - medic.health_care_certificate.save(request.user.username+"_"+myfile.name, im_io) + medic.health_care_certificate.save( + request.user.username+"_"+myfile.name, im_io) medic.save() except UnidentifiedImageError: error = True error_text = "Il file non è un immagine valida" - + # user requested file delete if request.POST["delete_vac"] == 'vac': medic.vac_certificate = None medic.save() @@ -153,9 +171,11 @@ def personal(request): medic.health_care_certificate = None medic.save() + # if there wasn't any error redirect to clear POST if not error: return HttpResponseRedirect("") + # check if user is in a group and set multiple choice to that if len(request.user.groups.values_list('name', flat=True)) == 0: branca_default = "selected" else: @@ -174,6 +194,7 @@ def personal(request): else: branca_default = "selected" + # set checkbox status rega = "" if medic.rega: rega = "checked='checked'" @@ -184,6 +205,7 @@ def personal(request): if medic.misc_bool: misc = "checked='checked'" + # set file name for uploaded files if (medic.vac_certificate != None): vac_name = os.path.basename(medic.vac_certificate.name) vac_name = vac_name[vac_name.find("_")+1:] @@ -196,6 +218,7 @@ def personal(request): else: card_name = '' + # fill context context = { 'first_name': request.user.first_name, 'last_name': request.user.last_name, @@ -244,6 +267,8 @@ def personal(request): return render(request, 'accounts/index.html', context) + +# simple terms page, only static html def terms(request): context = {} - return render(request, 'accounts/terms.html', context) \ No newline at end of file + return render(request, 'accounts/terms.html', context) diff --git a/client/templates/client/approve.html b/client/templates/client/approve.html index ddfc30c..3da2677 100644 --- a/client/templates/client/approve.html +++ b/client/templates/client/approve.html @@ -30,4 +30,10 @@ {% endif %} +{% endblock %} + +{% block script %} +$(document).ready(function(){ + $('.tooltipped').tooltip(); +}); {% endblock %} \ No newline at end of file diff --git a/client/templates/client/index.html b/client/templates/client/index.html index 1915792..1a63c2e 100644 --- a/client/templates/client/index.html +++ b/client/templates/client/index.html @@ -373,25 +373,31 @@ {% block script %} $(document).ready(function(){ - $('.collapsible').collapsible(); - $('.tap-target').tapTarget(); - $('.modal').modal(); $('.tooltipped').tooltip(); - {% if empty %} - $('.tap-target').tapTarget('open'); + {% if user.is_authenticated %} + {% if user.is_staff or perms.client.approved %} + $('.collapsible').collapsible(); + $('.tap-target').tapTarget(); + $('.modal').modal(); + {% if empty %} + $('.tap-target').tapTarget('open'); + {% endif %} + {% endif %} {% endif %} }); - -$('*').click(function(event) { - if (this === event.target) { - $('.tap-target').tapTarget('close'); +{% if user.is_authenticated %} + {% if user.is_staff or perms.client.approved %} + $('*').click(function(event) { + if (this === event.target) { + $('.tap-target').tapTarget('close'); + } + }); + function send(id) { + var form = document.getElementById('form') + var action = document.getElementById('action') + action.setAttribute('value', id); + form.submit() } -}); - -function send(id) { - var form = document.getElementById('form') - var action = document.getElementById('action') - action.setAttribute('value', id); - form.submit() -} -{% endblock %} \ No newline at end of file + {% endif %} +{% endif %} +{% endblock %} diff --git a/client/views.py b/client/views.py index ae5f2d5..b1b8297 100644 --- a/client/views.py +++ b/client/views.py @@ -12,12 +12,12 @@ from io import BytesIO import pdfkit import base64 -# Create your views here. - def index(request): context = {} + # check if user is logged if (request.user.is_authenticated): + # generate code if user has no code users = UserCode.objects.filter(user=request.user) code = None if (len(users) == 0): @@ -30,16 +30,21 @@ def index(request): userCode = UserCode(user=request.user, code=code, medic=medic) userCode.save() + # user action if request.method == "POST": + # get document id document = Document.objects.get(id=request.POST["action"][1:]) + # check if document is valid to modify if document.user != request.user: return if document.status == "ok" or document.status == "archive": return + # execute action if request.POST["action"][0] == 'f': + # generate approve pdf template = get_template('client/approve_doc_pdf.html') context = {'doc': document} html = template.render(context) @@ -47,20 +52,22 @@ def index(request): result = BytesIO(pdf) result.seek(0) return FileResponse(result, as_attachment=True, filename=document.document_type.name+".pdf") - elif request.POST["action"][0] == 'a': + # sign autosign doc if document.status == "autosign": document.status = "ok" document.save() return HttpResponseRedirect("/") elif request.POST["action"][0] == 'd': + # delete doc document.delete() return HttpResponseRedirect("/") elif request.POST["action"][0] == 'e': + # edit doc generate context and render edit page document_type = document.document_type context = { 'doctype': document_type, - } + } context['doc'] = document context['personal_data'] = document_type.personal_data context['medical_data'] = document_type.medical_data @@ -68,15 +75,19 @@ def index(request): keys = Keys.objects.filter(container=document_type) out_keys = [] for i in keys: - out_keys.append([i, KeyVal.objects.filter(Q(container=document) & Q(key=i.key))[0].value]) + out_keys.append([i, KeyVal.objects.filter( + Q(container=document) & Q(key=i.key))[0].value]) context['keys'] = out_keys context['custom_message'] = document_type.custom_message context['custom_message_text'] = document_type.custom_message_text return edit_wrapper(request, context) - documents = Document.objects.filter(Q(user=request.user) & ~Q(status='archive')) + # show only docs of the user and non archived + documents = Document.objects.filter( + Q(user=request.user) & ~Q(status='archive')) out = [] for i in documents: + # for every document prepare images in base64 personal = None medical = None vac_file = "" @@ -92,11 +103,14 @@ def index(request): if medical.health_care_certificate.name: with open(medical.health_care_certificate.name, 'rb') as image_file: - health_file = base64.b64encode(image_file.read()).decode() + health_file = base64.b64encode( + image_file.read()).decode() doc_group = i.user.groups.values_list('name', flat=True)[0] - out.append([i, KeyVal.objects.filter(container=i), personal, medical, doc_group, vac_file, health_file]) + out.append([i, KeyVal.objects.filter(container=i), + personal, medical, doc_group, vac_file, health_file]) + context = { "docs": out, "empty": len(out) == 0, @@ -108,6 +122,7 @@ def index(request): @login_required def approve(request): context = {} + # if user not approved and has enough data then give instructions how to approve user if not (request.user.is_staff or request.user.has_perm('approved')): usercode = UserCode.objects.filter(user=request.user)[0] okay = False @@ -118,26 +133,34 @@ def approve(request): else: return render(request, 'client/index.html', context) + @login_required def create(request): context = {} + # group name and obj parent_group = request.user.groups.values_list('name', flat=True)[ 0] group = Group.objects.get(name=parent_group) + + # get available types for user doctypes = DocumentType.objects.filter( (Q(group_private=False) | Q(group=group)) & Q(enabled=True)) out = [] for doc in doctypes: + # check if user has already that document type if len(Document.objects.filter(Q(user=request.user) & Q(document_type=doc))) == 0: out.append(doc) context['docs'] = out if request.method == "POST": if request.POST["action"] == "details": + # user has to select a document type if "doctype" not in request.POST.keys(): + # if no type selected throw error context['error'] = True context['error_text'] = "Seleziona un documento" else: + # gather data to ask to the user context['next'] = True document_type = DocumentType.objects.get( id=request.POST["doctype"]) @@ -153,71 +176,90 @@ def create(request): context['custom_message'] = document_type.custom_message context['custom_message_text'] = document_type.custom_message_text elif request.POST["action"] == "save": + # after type was selected it shows details to complete + + # get selected type document_type = DocumentType.objects.get( id=request.POST["doctype"]) + # get list of docs with that type current_docs = Document.objects.filter(document_type=document_type) if len(current_docs) > 0: + # if there is already a document with that type abort (user is cheating) return + # set default values usercode = UserCode.objects.filter(user=request.user)[0] code = 0 status = "wait" personal_data = None medical_data = None + # set to auto_sign if it is the case if document_type.auto_sign: status = "autosign" keys = [] + # copy personal data and medical data if document_type.personal_data: personal_data = PersonalData(email=request.user.email, parent_name=usercode.parent_name, via=usercode.via, cap=usercode.cap, country=usercode.country, - nationality=usercode.nationality, born_date=usercode.born_date, home_phone=usercode.home_phone, phone=usercode.phone) + nationality=usercode.nationality, born_date=usercode.born_date, home_phone=usercode.home_phone, phone=usercode.phone) personal_data.save() if document_type.medical_data: medic = usercode.medic - medical_data = MedicalData(vac_certificate=medic.vac_certificate, health_care_certificate=medic.health_care_certificate, emer_name=medic.emer_name, emer_relative=medic.emer_relative, cell_phone=medic.cell_phone, address=medic.address, emer_phone=medic.emer_phone, health_care=medic.health_care, injuries=medic.injuries, rc=medic.rc, rega=medic.rega, medic_name=medic.medic_name, medic_phone=medic.medic_phone, medic_address=medic.medic_address, sickness=medic.sickness, vaccine=medic.vaccine, tetanus_date=medic.tetanus_date, allergy=medic.allergy, drugs_bool=medic.drugs_bool, drugs=medic.drugs, misc_bool=medic.misc_bool, misc=medic.misc) + medical_data = MedicalData(vac_certificate=medic.vac_certificate, health_care_certificate=medic.health_care_certificate, emer_name=medic.emer_name, emer_relative=medic.emer_relative, cell_phone=medic.cell_phone, address=medic.address, emer_phone=medic.emer_phone, health_care=medic.health_care, injuries=medic.injuries, + rc=medic.rc, rega=medic.rega, medic_name=medic.medic_name, medic_phone=medic.medic_phone, medic_address=medic.medic_address, sickness=medic.sickness, vaccine=medic.vaccine, tetanus_date=medic.tetanus_date, allergy=medic.allergy, drugs_bool=medic.drugs_bool, drugs=medic.drugs, misc_bool=medic.misc_bool, misc=medic.misc) medical_data.save() + # generate document code while (True): code = randint(100000, 999999) if len(Document.objects.filter(code=code)) == 0: break + # save document document = Document( user=request.user, group=document_type.group, code=code, status=status, document_type=document_type, personal_data=personal_data, medical_data=medical_data) document.save() + # attach custom keys if document_type.custom_data: for i in request.POST.keys(): - if i == "doctype" or i=="csrfmiddlewaretoken" or i=="action": + if i == "doctype" or i == "csrfmiddlewaretoken" or i == "action": continue - key = KeyVal(container=document, key=Keys.objects.get(id=i).key, value=request.POST[i]) + key = KeyVal(container=document, key=Keys.objects.get( + id=i).key, value=request.POST[i]) key.save() return HttpResponseRedirect('/') return render(request, 'client/doc_create.html', context) + +# helper function to call edit_wrapper with empty context @login_required def edit(request): return edit_wrapper(request, {}) + @login_required def edit_wrapper(request, context): if request.method == "POST": if "action" not in request.POST.keys(): + # get document document = Document.objects.get(id=request.POST["doc"]) + # check if user has permission if document.user != request.user: return - + + # save again all data usercode = UserCode.objects.filter(user=document.user)[0] if document.document_type.personal_data: personal_data = PersonalData(email=request.user.email, parent_name=usercode.parent_name, via=usercode.via, cap=usercode.cap, country=usercode.country, - nationality=usercode.nationality, born_date=usercode.born_date, home_phone=usercode.home_phone, phone=usercode.phone) + nationality=usercode.nationality, born_date=usercode.born_date, home_phone=usercode.home_phone, phone=usercode.phone) personal_data.save() old_data = document.personal_data document.personal_data = personal_data @@ -226,18 +268,21 @@ def edit_wrapper(request, context): if document.document_type.medical_data: medic = usercode.medic - medical_data = MedicalData(vac_certificate=medic.vac_certificate, health_care_certificate=medic.health_care_certificate, emer_name=medic.emer_name, emer_relative=medic.emer_relative, cell_phone=medic.cell_phone, address=medic.address, emer_phone=medic.emer_phone, health_care=medic.health_care, injuries=medic.injuries, rc=medic.rc, rega=medic.rega, medic_name=medic.medic_name, medic_phone=medic.medic_phone, medic_address=medic.medic_address, sickness=medic.sickness, vaccine=medic.vaccine, tetanus_date=medic.tetanus_date, allergy=medic.allergy, drugs_bool=medic.drugs_bool, drugs=medic.drugs, misc_bool=medic.misc_bool, misc=medic.misc) + medical_data = MedicalData(vac_certificate=medic.vac_certificate, health_care_certificate=medic.health_care_certificate, emer_name=medic.emer_name, emer_relative=medic.emer_relative, cell_phone=medic.cell_phone, address=medic.address, emer_phone=medic.emer_phone, health_care=medic.health_care, injuries=medic.injuries, + rc=medic.rc, rega=medic.rega, medic_name=medic.medic_name, medic_phone=medic.medic_phone, medic_address=medic.medic_address, sickness=medic.sickness, vaccine=medic.vaccine, tetanus_date=medic.tetanus_date, allergy=medic.allergy, drugs_bool=medic.drugs_bool, drugs=medic.drugs, misc_bool=medic.misc_bool, misc=medic.misc) medical_data.save() old_data = document.medical_data document.medical_data = medical_data document.save() old_data.delete() + # update again custom keys if document.document_type.custom_data: for i in request.POST.keys(): - if i == "doc" or i=="csrfmiddlewaretoken": + if i == "doc" or i == "csrfmiddlewaretoken": continue - key = KeyVal.objects.filter(Q(container=document) & Q(key=Keys.objects.get(id=i).key))[0] + key = KeyVal.objects.filter(Q(container=document) & Q( + key=Keys.objects.get(id=i).key))[0] key.value = request.POST[i] key.save() @@ -245,11 +290,13 @@ def edit_wrapper(request, context): return render(request, 'client/doc_edit.html', context) + def about(request): + # very simple about page, get version from text file version = "" with open("version.txt", 'r') as f: version = f.read() if version.startswith("0"): version = "Beta " + version context = {"version": version} - return render(request, 'client/about.html', context) \ No newline at end of file + return render(request, 'client/about.html', context) diff --git a/server/templates/server/doc_list.html b/server/templates/server/doc_list.html index 7bdbb17..66ff997 100644 --- a/server/templates/server/doc_list.html +++ b/server/templates/server/doc_list.html @@ -434,6 +434,15 @@ +
+
+
+
+ {% if doc.7 %}{% endif %} +
+
+
+
{% endif %} diff --git a/server/views.py b/server/views.py index 01e8109..dec4e11 100644 --- a/server/views.py +++ b/server/views.py @@ -16,10 +16,12 @@ from datetime import timedelta import pytz import pdfkit from io import BytesIO -import os, base64 +import os +import base64 from PIL import Image, UnidentifiedImageError +# custom staff check function for non primary group staff members def isStaff(user): if user.is_staff: return True @@ -31,41 +33,46 @@ def isStaff(user): @user_passes_test(isStaff) def index(request): context = {} + # primary group name + object parent_group = request.user.groups.values_list('name', flat=True)[ 0] + group = Group.objects.get(name=parent_group) + # users from younger to older users = User.objects.filter(groups__name=parent_group).order_by("-id") users_out = [] + # only send part of the user data, only if user is approved for user in users: if not user.has_perm("client.approved") and not user.is_staff: continue users_out.append([user.username, user.first_name, - user.last_name]) + user.last_name]) - parent_group = request.user.groups.values_list('name', flat=True)[ - 0] - group = Group.objects.get(name=parent_group) + # if user is staff of not primary show only public types if request.user.is_staff: public_types = DocumentType.objects.filter( Q(group_private=False) | Q(group=group) & Q(enabled=True)).order_by("-id") else: public_types = DocumentType.objects.filter( Q(group_private=False) & Q(enabled=True)).order_by("-id") + + # count documents of that type to show statistics docs = [] for doc in public_types: ref_docs = Document.objects.filter(document_type=doc) docs.append([doc, len(ref_docs)]) + # don't list users if user is staff of not primary if request.user.is_staff: context = { 'docs': docs, 'users': users_out, - } + } else: context = { 'docs': docs, - } + } return render(request, 'server/index.html', context) @@ -74,13 +81,19 @@ def uapprove(request): context = {} data = [] if request.method == "POST": + # get group name and obj parent_group = request.user.groups.values_list('name', flat=True)[ 0] group = Group.objects.get(name=parent_group) + + # get permission object permission = Permission.objects.get(codename='approved') + + # parse text to array data = request.POST["codes"] data.replace("\r", "") data = data.split("\n") + # check if format is right for i in range(len(data)): if not data[i].startswith("U"): data[i] = data[i] + " - Formato errato" @@ -93,13 +106,16 @@ def uapprove(request): else: user = UserCode.objects.filter(code=data[i][1:])[0].user user.user_permissions.add(permission) + # if user not in any group add to the same group as staff if len(user.groups.values_list('name', flat=True)) == 0: user.groups.add(group) data[i] = data[i] + " - Ok" else: if user.groups.values_list('name', flat=True)[0] == parent_group: + # if user already in group do nothing data[i] = data[i] + " - Ok" else: + # if user in another group notify staff of group change user.groups.clear() user.groups.add(group) data[i] = data[i] + " - Ok, cambio branca" @@ -116,19 +132,24 @@ def uapprove(request): def docapprove(request): context = {} data = [] + + # group name and obj parent_group = request.user.groups.values_list('name', flat=True)[ 0] + group = Group.objects.get(name=parent_group) + # if user not staff of primary has only controll of non primary groups if request.user.is_staff: groups = request.user.groups.values_list('name', flat=True) else: groups = request.user.groups.values_list('name', flat=True)[1:] - group = Group.objects.get(name=parent_group) if request.method == "POST": + # parse text in array data = request.POST["codes"] data.replace("\r", "") data = data.split("\n") + # check if code valid for i in range(len(data)): print(Document.objects.filter(code=data[i])[0].group.name) if not data[i].isdigit(): @@ -138,10 +159,12 @@ def docapprove(request): elif len(Document.objects.filter(code=data[i])) == 0: data[i] = data[i] + " - Invalido" elif Document.objects.filter(code=data[i])[0].group.name not in groups: + # check if user has permission to approve document data[i] = data[i] + " - Invalido" else: document = Document.objects.filter(code=data[i])[0] if document.status == 'ok': + # do nothing document already approved data[i] = data[i] + " - Già approvato" else: document.status = 'ok' @@ -159,54 +182,80 @@ def docapprove(request): @staff_member_required def ulist(request): context = {} + # group name and obj parent_group = request.user.groups.values_list('name', flat=True)[0] group = Group.objects.get(name=parent_group) + if request.method == "POST": + # request to download document if request.POST["action"][0] == 'f': document = Document.objects.get(id=request.POST["action"][1:]) + # check if user has permission to view document if document.group == group: vac_file = "" health_file = "" sign_doc_file = "" + + # prepare pictures in base64 if document.medical_data: if document.medical_data.vac_certificate.name: with open(document.medical_data.vac_certificate.name, 'rb') as image_file: - vac_file = base64.b64encode(image_file.read()).decode() + vac_file = base64.b64encode( + image_file.read()).decode() if document.medical_data.health_care_certificate.name: with open(document.medical_data.health_care_certificate.name, 'rb') as image_file: - health_file = base64.b64encode(image_file.read()).decode() + health_file = base64.b64encode( + image_file.read()).decode() if document.signed_doc: with open(document.signed_doc.name, 'rb') as image_file: - sign_doc_file = base64.b64encode(image_file.read()).decode() + sign_doc_file = base64.b64encode( + image_file.read()).decode() + # get template and build context template = get_template('server/download_doc.html') - doc = [document, KeyVal.objects.filter(container=document), document.personal_data, document.medical_data, parent_group] - context = {'doc': doc, 'vac': vac_file, 'health': health_file, 'sign_doc_file': sign_doc_file} + doc = [document, KeyVal.objects.filter( + container=document), document.personal_data, document.medical_data, parent_group] + context = {'doc': doc, 'vac': vac_file, + 'health': health_file, 'sign_doc_file': sign_doc_file} + # render context html = template.render(context) + # render pdf using wkhtmltopdf pdf = pdfkit.from_string(html, False) result = BytesIO(pdf) result.seek(0) return FileResponse(result, as_attachment=True, filename=document.user.username+"_"+document.document_type.name+".pdf") + + # deapprove user elif request.POST["action"][0] == 'd': user = User.objects.get(id=request.POST["action"][1:]) + # check if user has permission to deapprove user if user.groups.all()[0] == group: content_type = ContentType.objects.get_for_model(Document) - permission = Permission.objects.get(content_type=content_type, codename="approved") + permission = Permission.objects.get( + content_type=content_type, codename="approved") user.user_permissions.remove(permission) return HttpResponseRedirect("ulist") - users = User.objects.filter(groups__name=parent_group).order_by("first_name") + # list users with their documents + users = User.objects.filter( + groups__name=parent_group).order_by("first_name") out = [] for user in users: + # list only approved users if not user.has_perm("client.approved") and not user.is_staff: continue usercode = UserCode.objects.filter(user=user)[0] - documents = Document.objects.filter(Q(user=user) & ~Q(status='archive') & Q(group__name=parent_group)) + # get all user documents + documents = Document.objects.filter(Q(user=user) & ~Q( + status='archive') & Q(group__name=parent_group)) + + # encode images in base64 vac_file = "" health_file = "" + sign_doc_file = "" if usercode.medic: if usercode.medic.vac_certificate.name: with open(usercode.medic.vac_certificate.name, 'rb') as image_file: @@ -215,7 +264,8 @@ def ulist(request): if usercode.medic.health_care_certificate.name: with open(usercode.medic.health_care_certificate.name, 'rb') as image_file: health_file = base64.b64encode(image_file.read()).decode() - out.append([user, usercode, parent_group, documents, vac_file, health_file]) + out.append([user, usercode, parent_group, + documents, vac_file, health_file]) context = {'users': out} return render(request, 'server/user_list.html', context) @@ -223,9 +273,12 @@ def ulist(request): @user_passes_test(isStaff) def doctype(request): context = {} + + # error variables to throw at user error = False error_text = "" + # init checkboxes public = True selfsign = True hidden = False @@ -242,21 +295,28 @@ def doctype(request): custom_check = 'checked="checked"' message_check = 'checked="checked"' group_check = 'checked="checked"' + if request.method == "POST": selected = [] + # if user not staff of primary get only non primary groups if request.user.is_staff: parent_groups = request.user.groups.values_list('name', flat=True) else: - parent_groups = request.user.groups.values_list('name', flat=True)[1:] + parent_groups = request.user.groups.values_list('name', flat=True)[ + 1:] + + # list all selected types for i in request.POST.keys(): if i.isdigit(): docc = DocumentType.objects.get(id=i) + # check if user has permission if docc.group.name in parent_groups: selected.append(docc) else: error = True error_text = "Non puoi modificare un documento non del tuo gruppo" + # execute action on selected types for i in selected: if request.POST["action"] == 'delete': try: @@ -271,6 +331,7 @@ def doctype(request): i.enabled = True i.save() + # check which filters are applied public = "filter_public" in request.POST selfsign = "filter_selfsign" in request.POST hidden = "filter_hidden" in request.POST @@ -280,6 +341,7 @@ def doctype(request): message = "filter_message" in request.POST group_bool = "filter_group" in request.POST + # check if request to clear filters if request.POST["action"] == 'clear': public = True selfsign = True @@ -290,15 +352,20 @@ def doctype(request): message = True group_bool = True + # group name and obj parent_group = request.user.groups.values_list('name', flat=True)[ 0] group = Group.objects.get(name=parent_group) + + # if user not staff of primary group show only public types if request.user.is_staff: public_types = DocumentType.objects.filter( Q(group_private=False) | Q(group=group)) else: public_types = DocumentType.objects.filter( Q(group_private=False)) + + # apply filters if not public: public_types = public_types.filter(group_private=True) public_check = "" @@ -324,6 +391,7 @@ def doctype(request): public_types = public_types.filter(custom_group=False) group_check = "" + # get custom keys from types out = [] for doc in public_types: custom_keys = Keys.objects.filter(container=doc) @@ -342,26 +410,33 @@ def doctype(request): 'group_check': group_check, 'error': error, 'error_text': error_text, - } + } return render(request, 'server/doc_type.html', context) @user_passes_test(isStaff) def doccreate(request): context = {} + + # if user is not staff of primary set default group to secondary and default public type if request.user.is_staff: groups = request.user.groups.values_list('name', flat=True) parent_group = request.user.groups.values_list('name', flat=True)[ 0] + group_private = False + private_check = 'checked="checked"' else: groups = request.user.groups.values_list('name', flat=True)[1:] parent_group = request.user.groups.values_list('name', flat=True)[ 1] + group_private = True + private_check = '' + # get group obj group = Group.objects.get(name=parent_group) + # init checkboxes enabled = False - group_private = False personal_data = False medical_data = False custom_data = False @@ -370,22 +445,15 @@ def doccreate(request): custom_group = "" enabled_check = 'checked="checked"' - private_check = 'checked="checked"' personal_check = 'checked="checked"' sign_check = 'checked="checked"' medical_check = "" custom_check = "" custom_message_check = "" - context = { - "enabled_check": enabled_check, - "private_check": private_check, - "sign_check": sign_check, - "personal_check": personal_check, - "medical_check": medical_check, - "custom_check": custom_check, - "custom_message_check": custom_message_check, - } + + # if type create request sent if request.method == "POST": + # gather inserted data enabled = "enabled" in request.POST.keys() auto_sign = "sign" not in request.POST.keys() group_private = "group_private" in request.POST.keys() @@ -397,12 +465,24 @@ def doccreate(request): name = request.POST["name"] custom_group = request.POST["custom_group"] + # if group not primary and not public throw error + if group_private == True and not request.user.is_staff: + context["error"] = "true" + context["error_text"] = "Non puoi creare un documento non pubblico per un gruppo non primario" + return render(request, 'server/doc_create.html', context) + + # if already existing name throw error if len(DocumentType.objects.filter(name=name)) > 0: context["error"] = "true" context["error_text"] = "Questo nome esiste già. Prego usarne un altro." return render(request, 'server/doc_create.html', context) + # check if custom group permissions not met or non public document if custom_group != "": + if group_private == True: + context["error"] = "true" + context["error_text"] = "Non puoi creare un documento non pubblico per un gruppo non primario" + return render(request, 'server/doc_create.html', context) if custom_group not in groups: context["error"] = "true" context["error_text"] = "Non puoi creare un tipo assegnato ad un gruppo di cui non fai parte" @@ -411,9 +491,12 @@ def doccreate(request): group = Group.objects.filter(name=custom_group)[0] custom_group_bool = True + # create type doctype = DocumentType( custom_group=custom_group_bool, auto_sign=auto_sign, custom_message=custom_message, custom_message_text=custom_message_text, name=request.POST["name"], enabled=enabled, group_private=group_private, group=group, personal_data=personal_data, medical_data=medical_data, custom_data=custom_data) doctype.save() + + # create custom keys if custom_data: custom = request.POST["custom"] custom.replace("\r", "") @@ -421,27 +504,46 @@ def doccreate(request): for i in custom: key = Keys(key=i, container=doctype) key.save() + return HttpResponseRedirect('doctype') + # build context + context = { + "enabled_check": enabled_check, + "private_check": private_check, + "sign_check": sign_check, + "personal_check": personal_check, + "medical_check": medical_check, + "custom_check": custom_check, + "custom_message_check": custom_message_check, + } + return render(request, 'server/doc_create.html', context) @user_passes_test(isStaff) def doclist(request): context = {} + + # group name and obj parent_group = request.user.groups.values_list('name', flat=True)[ 0] group = Group.objects.get(name=parent_group) + # if user not staff of primary get secondary groups if request.user.is_staff: parent_groups = request.user.groups.values_list('name', flat=True) else: parent_groups = request.user.groups.values_list('name', flat=True)[1:] + # create typezone zurich = pytz.timezone('Europe/Zurich') + + # init error variables for users error = False error_text = "" + # init checkboxes for filter hidden = False wait = True selfsign = True @@ -453,8 +555,12 @@ def doclist(request): selfsign_check = 'checked="checked"' ok_check = 'checked="checked"' signdoc_check = 'checked="checked"' + + # set default dates for filters newer = zurich.localize(dateparser.parse("1970-01-01")) older = zurich.localize(datetime.now()) + + # init chips values owner = [] types = [] groups = [] @@ -463,28 +569,38 @@ def doclist(request): chips_groups = [] if request.method == "POST": + # if download request if request.POST["action"][0] == 'k': document = Document.objects.get(id=request.POST["action"][1:]) + # check if user has permission to view doc if document.group.name in parent_groups: vac_file = "" health_file = "" sign_doc_file = "" + + # prepare images in base64 if document.medical_data: if document.medical_data.vac_certificate.name: with open(document.medical_data.vac_certificate.name, 'rb') as image_file: - vac_file = base64.b64encode(image_file.read()).decode() + vac_file = base64.b64encode( + image_file.read()).decode() if document.medical_data.health_care_certificate.name: with open(document.medical_data.health_care_certificate.name, 'rb') as image_file: - health_file = base64.b64encode(image_file.read()).decode() - + health_file = base64.b64encode( + image_file.read()).decode() + if document.signed_doc: with open(document.signed_doc.name, 'rb') as image_file: - sign_doc_file = base64.b64encode(image_file.read()).decode() + sign_doc_file = base64.b64encode( + image_file.read()).decode() + # build with template and render template = get_template('server/download_doc.html') - doc = [document, KeyVal.objects.filter(container=document), document.personal_data, document.medical_data, parent_group] - context = {'doc': doc, 'vac': vac_file, 'health': health_file, 'sign_doc_file': sign_doc_file} + doc = [document, KeyVal.objects.filter( + container=document), document.personal_data, document.medical_data, parent_group] + context = {'doc': doc, 'vac': vac_file, + 'health': health_file, 'sign_doc_file': sign_doc_file} html = template.render(context) pdf = pdfkit.from_string(html, False) result = BytesIO(pdf) @@ -492,6 +608,7 @@ def doclist(request): return FileResponse(result, as_attachment=True, filename=document.user.username+"_"+document.document_type.name+".pdf") + # get selected documents and check if user has permission to view selected = [] for i in request.POST.keys(): if i.isdigit(): @@ -499,6 +616,7 @@ def doclist(request): if docc.group.name in parent_groups: selected.append(docc) + # execute action on selected documents for i in selected: if request.POST["action"] == 'delete' and settings.DEBUG: i.delete() @@ -522,35 +640,41 @@ def doclist(request): else: error = True error_text = "Non puoi dearchiviare un documento non archiviato" - + + # get filter values hidden = "filter_hidden" in request.POST wait = "filter_wait" in request.POST selfsign = "filter_selfsign" in request.POST ok = "filter_ok" in request.POST signdoc = "filter_signdoc" in request.POST newer = zurich.localize(dateparser.parse(request.POST["newer"])) - older = zurich.localize(dateparser.parse(request.POST["older"]) + timedelta(days=1)) + older = zurich.localize(dateparser.parse( + request.POST["older"]) + timedelta(days=1)) owner = request.POST["owner"].split("^|") types = request.POST["type"].split("^|") groups = request.POST["groups"].split("^|") + # clear filters if request.POST["action"] == 'clear': hidden = False wait = True selfsign = True ok = True + signdoc = False newer = zurich.localize(dateparser.parse("1970-01-01")) older = zurich.localize(datetime.now()) owner = [] types = [] groups = [] + # filter documents based on group of staff q_obj = Q() for i in parent_groups: q_obj |= Q(group__name=i) documents = Document.objects.filter(q_obj) + # filter documents if not hidden: documents = documents.filter(~Q(status="archive")) hidden_check = "" @@ -566,8 +690,10 @@ def doclist(request): if not signdoc: signdoc_check = "" + # filter date range documents = documents.filter(compilation_date__range=[newer, older]) + # filter types, owner, groups using chips if len(types) > 0: if types[0] != "": q_obj = Q() @@ -598,14 +724,17 @@ def doclist(request): out = [] for i in documents: + # filter for confirmed with attachment documents and approved if signdoc: if i.status == "ok" and not i.signed_doc: continue + # prepare images in base64 personal = None medical = None vac_file = "" health_file = "" + sign_doc_file = "" if i.personal_data: personal = i.personal_data if i.medical_data: @@ -618,12 +747,21 @@ def doclist(request): with open(medical.health_care_certificate.name, 'rb') as image_file: health_file = base64.b64encode(image_file.read()).decode() + if i.signed_doc: + with open(i.signed_doc.name, 'rb') as image_file: + sign_doc_file = base64.b64encode( + image_file.read()).decode() + doc_group = i.user.groups.values_list('name', flat=True)[0] - out.append([i, KeyVal.objects.filter(container=i), personal, medical, doc_group, vac_file, health_file]) + out.append([i, KeyVal.objects.filter(container=i), personal, + medical, doc_group, vac_file, health_file, sign_doc_file]) - auto_types = DocumentType.objects.filter(Q(group_private=False) | Q(group=group)) + # get types and users for chips autocompletation + auto_types = DocumentType.objects.filter( + Q(group_private=False) | Q(group=group)) users = User.objects.filter(groups__name=parent_group) + context = { "types": auto_types, "users": users, @@ -642,12 +780,13 @@ def doclist(request): 'error': error, 'error_text': error_text, 'settings': settings, - } + } return render(request, 'server/doc_list.html', context) @user_passes_test(isStaff) def upload_doc(request): + # setup group based on staff primary or not parent_group = request.user.groups.values_list('name', flat=True)[ 0] group = Group.objects.get(name=parent_group) @@ -656,12 +795,14 @@ def upload_doc(request): else: groups = request.user.groups.values_list('name', flat=True)[1:] - message = "" + # setup variables for error text and success text error = False success = False error_text = "" success_text = "" + document = None + # parse document code and check for permissions if request.method == "POST": data = request.POST["code"] if not data.isdigit(): @@ -677,7 +818,10 @@ def upload_doc(request): error_text = "Codice invalido" error = True else: + # get document document = Document.objects.filter(code=data)[0] + + # prepare success message if document.status == 'ok': success_text = "File caricato" success = True @@ -687,11 +831,13 @@ def upload_doc(request): success_text = "Documento approvato e file caricato" success = True + # check for errors and upload files if "doc_sign" in request.FILES and not error: myfile = request.FILES['doc_sign'] try: im = Image.open(myfile) im_io = BytesIO() + # compress image in WEBP im.save(im_io, 'WEBP', quality=50) document.signed_doc.save(data+"_"+myfile.name, im_io) document.save() @@ -703,26 +849,29 @@ def upload_doc(request): error_text = "Prego caricare un file" context = { - "message": message, "error": error, "error_text": error_text, "success": success, "success_text": success_text, - } + return render(request, 'server/upload_doc.html', context) @user_passes_test(isStaff) def docpreview(request): context = {} + # check for permissions if request.user.is_staff: groups = request.user.groups.values_list('name', flat=True) else: groups = request.user.groups.values_list('name', flat=True)[1:] if request.method == "POST": + # get document code code = request.POST["preview"] + + # check if code valid and user has permission if not code.isdigit(): return render(request, 'server/download_doc.html', context) if len(Document.objects.filter(code=code)) == 0: @@ -730,7 +879,10 @@ def docpreview(request): if Document.objects.filter(code=code)[0].group.name not in groups: return render(request, 'server/download_doc.html', context) + # get document document = Document.objects.filter(code=code)[0] + + # prepare images in base64 vac_file = "" health_file = "" sign_doc_file = "" @@ -746,8 +898,10 @@ def docpreview(request): with open(document.signed_doc.name, 'rb') as image_file: sign_doc_file = base64.b64encode(image_file.read()).decode() - template = get_template('server/download_doc.html') - doc = [document, KeyVal.objects.filter(container=document), document.personal_data, document.medical_data, parent_group] - context = {'doc': doc, 'vac': vac_file, 'health': health_file, 'sign_doc_file': sign_doc_file} + # prepare context + doc = [document, KeyVal.objects.filter( + container=document), document.personal_data, document.medical_data, parent_group] + context = {'doc': doc, 'vac': vac_file, + 'health': health_file, 'sign_doc_file': sign_doc_file} - return render(request, 'server/download_doc.html', context) \ No newline at end of file + return render(request, 'server/download_doc.html', context) -- cgit v1.2.1