aboutsummaryrefslogtreecommitdiffstats
path: root/server/views.py
diff options
context:
space:
mode:
authorAndrea Lepori <alepori@student.ethz.ch>2020-08-09 18:19:11 +0200
committerAndrea Lepori <alepori@student.ethz.ch>2020-08-09 18:19:11 +0200
commit50798f2814f397fbdd85b70dabca9dfb26d4cd02 (patch)
treedb0489a2a16c23f016fb89d74932fdbb6a8d9b9d /server/views.py
parentremove old migrations (diff)
downloadscout-subs-50798f2814f397fbdd85b70dabca9dfb26d4cd02.tar.gz
scout-subs-50798f2814f397fbdd85b70dabca9dfb26d4cd02.zip
comment code, minor bug fixes
Diffstat (limited to 'server/views.py')
-rw-r--r--server/views.py250
1 files changed, 202 insertions, 48 deletions
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)