aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--accounts/templates/accounts/index.html51
-rw-r--r--accounts/views.py357
-rw-r--r--client/migrations/0012_remove_usercode_midata_code.py17
-rw-r--r--client/models.py1
-rw-r--r--templates/registration/base_client.html4
-rw-r--r--templates/registration/login.html2
-rw-r--r--version.txt2
7 files changed, 253 insertions, 181 deletions
diff --git a/accounts/templates/accounts/index.html b/accounts/templates/accounts/index.html
index 341fd7d..06dcff2 100644
--- a/accounts/templates/accounts/index.html
+++ b/accounts/templates/accounts/index.html
@@ -313,12 +313,13 @@
</div>
</div>
</div>
+</form>
<div id="settings" class="row">
<div class="col l8 offset-l2 s12">
<div class="card-panel">
<div class="row">
<div class="col s12">
- <h6>Collegamento con MiData</h6>
+ <h5>Collegamento con MiData</h5>
</div>
</div>
{% if midata_user %}
@@ -354,10 +355,49 @@
</div>
</div>
{% endif %}
+ <div class="row">
+ <div class="col s12">
+ <h5>Cambia password</h5>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <form method="post">
+ {% csrf_token %}
+ <input type="hidden" name="action" id="action" value="password">
+ {% if usable_password %}
+ <div class="row">
+ <div class="col s12">
+ <input id="old_password" type="password">
+ <label for="old_password">Password attuale</label>
+ </div>
+ </div>
+ {% else %}
+ <input id="old_password" type="hidden" value="">
+ {% endif %}
+ <div class="row">
+ <div class="col s12">
+ <input id="new_password1" type="password">
+ <label for="new_password1">Nuova password</label>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <input id="new_password2" type="password">
+ <label for="new_password2">Conferma nuova password</label>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col s12">
+ <button type="submit" class="btn waves-effect waves-light {{color}}">Salva</button>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
</div>
</div>
</div>
-</form>
{% endblock %}
{% block script %}
@@ -414,10 +454,9 @@ $(document).ready(function() {
$('.datepicker').datepicker(options);
$('.tabs').tabs();
$('select').formSelect();
- {% if error %}
- M.toast({html: '{{ error_text}}', classes: 'orange'})
- {% endif %}
-
+ {% for error in errors %}
+ M.toast({html: '{{ error }}', classes: 'orange'})
+ {% endfor %}
document.getElementById("vac_certificate").onchange = function() {
for (i=0; i < this.files.length; i++) {
if(this.files[i].size > 1048576*10) {
diff --git a/accounts/views.py b/accounts/views.py
index 598d300..21f33da 100644
--- a/accounts/views.py
+++ b/accounts/views.py
@@ -1,8 +1,7 @@
from django.shortcuts import render
from django.urls import reverse
-from django.shortcuts import redirect
from django.conf import settings
-from django.contrib.auth.forms import UserCreationForm
+from django.contrib.auth.forms import PasswordChangeForm, UserCreationForm
from django.contrib.auth.models import User
from django.contrib.auth import login, authenticate, logout
from django.http import FileResponse
@@ -50,11 +49,16 @@ def get_oauth_data(token):
# send to hitobito request to get token
def oauth_login(request):
redirect_uri = request.build_absolute_uri(reverse('auth'))
+
+ if not request.GET["next"]:
+ redirect_uri += "?next=/"
+ else:
+ redirect_uri += "?next=" + request.GET["next"]
+
return hitobito.authorize_redirect(request, redirect_uri)
# callback after acquiring token
def auth(request):
- code = request.GET["code"]
token = hitobito.authorize_access_token(request)
# request data from user account
@@ -77,10 +81,9 @@ def auth(request):
usercode[0].country = resp_data["town"]
usercode[0].born_date = dateparser.parse(resp_data["birthday"])
usercode[0].midata_token = token["access_token"]
- usercode[0].midata_code = code
usercode[0].save()
- return HttpResponseRedirect('/')
+ return HttpResponseRedirect(request.GET["next"])
user = User.objects.create_user(resp_data["email"], resp_data["email"])
@@ -92,7 +95,7 @@ def auth(request):
medic = MedicalData()
medic.save()
- userCode = UserCode(user=user, code=code, medic=medic, midata_id=resp_data["id"], midata_token=token["access_token"], midata_code=code)
+ userCode = UserCode(user=user, code=code, medic=medic, midata_id=resp_data["id"], midata_token=token["access_token"])
user.first_name = resp_data["first_name"]
user.last_name = resp_data["last_name"]
user.email = resp_data["email"]
@@ -106,7 +109,7 @@ def auth(request):
login(request, user)
- return HttpResponseRedirect('/')
+ return HttpResponseRedirect(request.GET["next"])
# send to hitobito request to get token
@login_required
@@ -116,10 +119,12 @@ def oauth_connect(request):
@login_required
def oauth_disconnect(request):
+ if not request.user.has_usable_password():
+ return personal_wrapper(request, ["Il tuo utente non ha una password impostata, impostare una password prima di scollegarlo da MiData"])
+
usercode = UserCode.objects.filter(user=request.user)[0]
usercode.midata_id = 0
usercode.midata_token = ""
- usercode.midata_code = ""
usercode.save()
return HttpResponseRedirect(reverse("personal") + "#settings")
@@ -135,13 +140,12 @@ def auth_connect(request):
# check that account is not linked to another
existing_codes = UserCode.objects.filter(midata_id=resp_data["id"])
if len(existing_codes) > 0:
- return personal_wrapper(request, True, "Questo utente è già collegato ad un altro")
+ return personal_wrapper(request, ["Questo utente è già collegato ad un altro"])
# save id to user
usercode = UserCode.objects.filter(user=request.user)[0]
usercode.midata_id = resp_data["id"]
usercode.midata_token = token["access_token"]
- usercode.midata_code = request.GET["code"]
usercode.save()
return HttpResponseRedirect(reverse("personal") + "#settings")
@@ -199,12 +203,12 @@ def signup(request):
# create wrapper to send custom error from other views (oauth connect/disconnect)
@login_required
def personal(request):
- return personal_wrapper(request, False, "")
+ return personal_wrapper(request, [])
@login_required
-def personal_wrapper(request, error, error_text):
+def personal_wrapper(request, errors):
context = {}
- # additional user informations
+ # additional user information
usercode = UserCode.objects.filter(user=request.user)[0]
# medical info
medic = usercode.medic
@@ -238,7 +242,7 @@ def personal_wrapper(request, error, error_text):
im_io.seek(0)
return FileResponse(im_io, as_attachment=True, filename=filename)
- if request.POST['action'] == "download_health":
+ elif request.POST['action'] == "download_health":
if medic.health_care_certificate != None:
filename = os.path.basename(medic.health_care_certificate.name)
filename = filename[filename.find("_")+1:]
@@ -253,172 +257,186 @@ def personal_wrapper(request, error, error_text):
im_io.seek(0)
return FileResponse(im_io, 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"]
- request.user.save()
- usercode.parent_name = request.POST["parent_name"]
- usercode.via = request.POST["via"]
- usercode.cap = request.POST["cap"]
- usercode.country = request.POST["country"]
- usercode.nationality = request.POST["nationality"]
- usercode.born_date = dateparser.parse(request.POST["birth_date"])
- usercode.home_phone = request.POST["home_phone"]
- usercode.phone = request.POST["phone"]
- usercode.school = request.POST["school"]
- usercode.avs_number = request.POST["avs_number"]
-
- if request.POST["year"].isdigit():
- usercode.year = request.POST["year"]
+ elif request.POST['action'] == "password":
+ # get form object
+ print(request.POST)
+
+ # if form is valid and terms were accepted save user
+ password_errors = []
+ for err in password_errors:
+ if err.code == "password_mismatch":
+ errors.append("Le due password non sono uguali")
+ elif err.code == "password_too_similar":
+ errors.append("La password è troppo simile all'username")
+ elif err.code == "password_too_short":
+ errors.append("La password è troppo corta")
+ elif err.code == "password_too_common":
+ errors.append("La password è troppo comune")
+ elif err.code == "password_entirely_numeric":
+ errors.append("La password deve contenere lettere")
+ elif err.code == "password_incorrect":
+ errors.append("La password attuale è incorretta")
+
else:
- error = True
- error_text = "L'anno scolastico deve essere un numero"
+ # 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"]
+ request.user.save()
+ usercode.parent_name = request.POST["parent_name"]
+ usercode.via = request.POST["via"]
+ usercode.cap = request.POST["cap"]
+ usercode.country = request.POST["country"]
+ usercode.nationality = request.POST["nationality"]
+ usercode.born_date = dateparser.parse(request.POST["birth_date"])
+ usercode.home_phone = request.POST["home_phone"]
+ usercode.phone = request.POST["phone"]
+ usercode.school = request.POST["school"]
+ usercode.avs_number = request.POST["avs_number"]
+
+ if request.POST["year"].isdigit():
+ usercode.year = request.POST["year"]
+ else:
+ errors.append("L'anno scolastico deve essere un numero")
- usercode.save()
+ usercode.save()
- medic.emer_name = request.POST["emer_name"]
- medic.emer_relative = request.POST["emer_relative"]
- medic.cell_phone = request.POST["cell_phone"]
- medic.address = request.POST["address"]
- medic.emer_phone = request.POST["emer_phone"]
- medic.health_care = request.POST["health_care"]
- medic.injuries = request.POST["injuries"]
- medic.rc = request.POST["rc"]
- medic.rega = "rega" in request.POST
- medic.medic_name = request.POST["medic_name"]
- medic.medic_phone = request.POST["medic_phone"]
- medic.medic_address = request.POST["medic_address"]
- medic.sickness = request.POST["sickness"]
- medic.vaccine = request.POST["vaccine"]
- medic.tetanus_date = dateparser.parse(request.POST["tetanus_date"])
- medic.allergy = request.POST["allergy"]
- medic.drugs_bool = "drugs_bool" in request.POST
- medic.drugs = request.POST["drugs"]
- medic.misc_bool = "misc_bool" in request.POST
- medic.misc = request.POST["misc"]
- medic.save()
-
- if request.POST["birth_date"] == "" or request.POST["birth_date"] == "01 Gennaio 1970" or request.POST["birth_date"] == "None":
- validation_dic["birth_date"] = 'class="datepicker validate invalid" required="" aria-required="true"'
- error = True
- error_text = "Alcuni campi richiesti non sono stati compilati"
- else:
- validation_dic["birth_date"] = 'class="datepicker validate" required="" aria-required="true"'
+ medic.emer_name = request.POST["emer_name"]
+ medic.emer_relative = request.POST["emer_relative"]
+ medic.cell_phone = request.POST["cell_phone"]
+ medic.address = request.POST["address"]
+ medic.emer_phone = request.POST["emer_phone"]
+ medic.health_care = request.POST["health_care"]
+ medic.injuries = request.POST["injuries"]
+ medic.rc = request.POST["rc"]
+ medic.rega = "rega" in request.POST
+ medic.medic_name = request.POST["medic_name"]
+ medic.medic_phone = request.POST["medic_phone"]
+ medic.medic_address = request.POST["medic_address"]
+ medic.sickness = request.POST["sickness"]
+ medic.vaccine = request.POST["vaccine"]
+ medic.tetanus_date = dateparser.parse(request.POST["tetanus_date"])
+ medic.allergy = request.POST["allergy"]
+ medic.drugs_bool = "drugs_bool" in request.POST
+ medic.drugs = request.POST["drugs"]
+ medic.misc_bool = "misc_bool" in request.POST
+ medic.misc = request.POST["misc"]
+ medic.save()
- for i in required_fields:
- if request.POST[i] == "":
- error = True
- error_text = "Alcuni campi richiesti non sono stati compilati"
- validation_dic[i] = 'class="validate invalid" required="" aria-required="true"'
+ missing_fields = False
+ if request.POST["birth_date"] == "" or request.POST["birth_date"] == "01 Gennaio 1970" or request.POST["birth_date"] == "None":
+ validation_dic["birth_date"] = 'class="datepicker validate invalid" required="" aria-required="true"'
+ missing_fields = True
else:
- validation_dic[i] = 'class="validate" required="" aria-required="true"'
-
- # 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:
- files = request.FILES.getlist('vac_certificate')
- name = files[0].name
- try:
- # if multiple files concatenate pictures
- im = Image.new("RGB", (0, 0), (255, 255, 255))
- for f in files:
- if f.name.endswith(".pdf"):
- images = convert_from_bytes(f.read())
- for i in images:
+ validation_dic["birth_date"] = 'class="datepicker validate" required="" aria-required="true"'
+
+ for i in required_fields:
+ if request.POST[i] == "":
+ missing_fields = True
+ validation_dic[i] = 'class="validate invalid" required="" aria-required="true"'
+ else:
+ validation_dic[i] = 'class="validate" required="" aria-required="true"'
+
+ if missing_fields:
+ errors.append("Alcuni campi richiesti non sono stati compilati")
+
+ # 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:
+ files = request.FILES.getlist('vac_certificate')
+ name = files[0].name
+ try:
+ # if multiple files concatenate pictures
+ im = Image.new("RGB", (0, 0), (255, 255, 255))
+ for f in files:
+ if f.name.endswith(".pdf"):
+ images = convert_from_bytes(f.read())
+ for i in images:
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+ else:
+ i = Image.open(f)
dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
dst.paste(im, (0, 0))
dst.paste(i, (0, im.height))
im = dst
- else:
- i = Image.open(f)
- dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
- dst.paste(im, (0, 0))
- dst.paste(i, (0, im.height))
- im = dst
- im_io = BytesIO()
- # resize image if larger than max value
- if im.height > 16383:
- im = im.resize((round(im.width/im.height*16383), 16383))
- # compress image in WEBP
- im.save(im_io, 'WEBP', quality=50, method=4)
- medic.vac_certificate.save(
- request.user.username+"_"+name, im_io)
- medic.save()
- except UnidentifiedImageError:
- error = True
- error_text = "Il file non è un immagine valida"
- except PDFPageCountError:
- error = True
- error_text = "Il file non è un pdf valido"
- except PDFSyntaxError:
- error = True
- error_text = "Il file non è un pdf valido"
- except IOError:
- error = True
- error_text = "Il file è un immagine troppo grande"
-
- if "health_care_certificate" in request.FILES:
- files = request.FILES.getlist('health_care_certificate')
- name = files[0].name
- try:
- # if multiple files concatenate pictures
- im = Image.new("RGB", (0, 0), (255, 255, 255))
- for f in files:
- if f.name.endswith(".pdf"):
- images = convert_from_bytes(f.read())
- for i in images:
+ im_io = BytesIO()
+ # resize image if larger than max value
+ if im.height > 16383:
+ im = im.resize((round(im.width/im.height*16383), 16383))
+ # compress image in WEBP
+ im.save(im_io, 'WEBP', quality=50, method=4)
+ medic.vac_certificate.save(
+ request.user.username+"_"+name, im_io)
+ medic.save()
+ except UnidentifiedImageError:
+ errors.append("Il certificato delle vaccinazioni non è un immagine valida")
+ except PDFPageCountError:
+ errors.append("Il certificato delle vaccinazioni non è un pdf valido")
+ except PDFSyntaxError:
+ errors.append("Il certificato delle vaccinazioni non è un pdf valido")
+ except IOError:
+ errors.append("Il certificato delle vaccinazioni è un immagine troppo grande")
+
+ if "health_care_certificate" in request.FILES:
+ files = request.FILES.getlist('health_care_certificate')
+ name = files[0].name
+ try:
+ # if multiple files concatenate pictures
+ im = Image.new("RGB", (0, 0), (255, 255, 255))
+ for f in files:
+ if f.name.endswith(".pdf"):
+ images = convert_from_bytes(f.read())
+ for i in images:
+ dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
+ dst.paste(im, (0, 0))
+ dst.paste(i, (0, im.height))
+ im = dst
+ else:
+ i = Image.open(f)
dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
dst.paste(im, (0, 0))
dst.paste(i, (0, im.height))
im = dst
- else:
- i = Image.open(f)
- dst = Image.new('RGB', (max(im.width, i.width), im.height + i.height), (255, 255, 255))
- dst.paste(im, (0, 0))
- dst.paste(i, (0, im.height))
- im = dst
- im_io = BytesIO()
- # resize image if larger than max value
- if im.height > 16383:
- im = im.resize((round(im.width/im.height*16383), 16383))
- # compress image in WEBP
- im.save(im_io, 'WEBP', quality=50, method=4)
- medic.health_care_certificate.save(
- request.user.username+"_"+name, im_io)
+ im_io = BytesIO()
+ # resize image if larger than max value
+ if im.height > 16383:
+ im = im.resize((round(im.width/im.height*16383), 16383))
+ # compress image in WEBP
+ im.save(im_io, 'WEBP', quality=50, method=4)
+ medic.health_care_certificate.save(
+ request.user.username+"_"+name, im_io)
+ medic.save()
+ except UnidentifiedImageError:
+ errors.append("La tessera della cassa malati non è un immagine valida")
+ except PDFPageCountError:
+ errors.append("La tessera della cassa malati non è un pdf valido")
+ except PDFSyntaxError:
+ errors.append("La tessera della cassa malati non è un pdf valido")
+ except IOError:
+ errors.append("La tessera della cassa malati è un immagine troppo grande")
+
+ # user requested file delete
+ if request.POST["delete_vac"] == 'vac':
+ medic.vac_certificate = None
medic.save()
- except UnidentifiedImageError:
- error = True
- error_text = "Il file non è un immagine valida"
- except PDFPageCountError:
- error = True
- error_text = "Il file non è un pdf valido"
- except PDFSyntaxError:
- error = True
- error_text = "Il file non è un pdf valido"
- except IOError:
- error = True
- error_text = "Il file è un immagine troppo grande"
-
- # user requested file delete
- if request.POST["delete_vac"] == 'vac':
- medic.vac_certificate = None
- medic.save()
- if request.POST["delete_health"] == 'health':
- medic.health_care_certificate = None
- medic.save()
+ if request.POST["delete_health"] == 'health':
+ medic.health_care_certificate = None
+ medic.save()
- # if there wasn't any error redirect to clear POST
- if not error:
- return HttpResponseRedirect("")
+ # if there wasn't any error redirect to clear POST
+ if len(errors) == 0:
+ return HttpResponseRedirect("")
else:
# no post, create empty validation
@@ -476,15 +494,8 @@ def personal_wrapper(request, error, error_text):
resp = get_oauth_data(usercode.midata_token)
if resp.status_code != 200:
- request.GET["code"] = usercode.midata_code
- token = hitobito.authorize_access_token(request)
- usercode.midata_token = token["access_token"]
- usercode.save()
- resp = get_oauth_data(usercode.midata_token)
-
- if resp.status_code != 200:
logout(request)
- return HttpResponseRedirect("/")
+ return HttpResponseRedirect(request.path_info)
resp_data = resp.json()
@@ -500,6 +511,8 @@ def personal_wrapper(request, error, error_text):
usercode.born_date = dateparser.parse(resp_data["birthday"])
usercode.save()
+ usable_password = request.user.has_usable_password()
+
# fill context
context = {
'validation_dic': validation_dic,
@@ -545,10 +558,10 @@ def personal_wrapper(request, error, error_text):
'misc': medic.misc,
'health_care_certificate': card_name,
'vac_certificate': vac_name,
- 'error': error,
- 'error_text': error_text,
+ 'errors': errors,
'midata_user': midata_user,
'midata_disable': midata_disable,
+ 'usable_password': usable_password,
}
return render(request, 'accounts/index.html', context)
diff --git a/client/migrations/0012_remove_usercode_midata_code.py b/client/migrations/0012_remove_usercode_midata_code.py
new file mode 100644
index 0000000..3f3d876
--- /dev/null
+++ b/client/migrations/0012_remove_usercode_midata_code.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.4 on 2022-01-04 15:09
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('client', '0011_usercode_midata_code'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='usercode',
+ name='midata_code',
+ ),
+ ]
diff --git a/client/models.py b/client/models.py
index 5f0da0d..b94806b 100644
--- a/client/models.py
+++ b/client/models.py
@@ -115,7 +115,6 @@ class UserCode(models.Model):
avs_number = models.CharField(default="", max_length=250)
midata_id = models.IntegerField(default=0)
midata_token = models.CharField(default="", max_length=1024)
- midata_code = models.CharField(default="", max_length=1024)
class GroupSettings(models.Model):
group = models.ForeignKey(Group, default=None, on_delete=models.CASCADE)
diff --git a/templates/registration/base_client.html b/templates/registration/base_client.html
index d90462c..cfb6024 100644
--- a/templates/registration/base_client.html
+++ b/templates/registration/base_client.html
@@ -12,6 +12,10 @@
color: {{hexcolor}} !important;
}
+ input[type=password]:focus + label, .materialize-textarea:focus:not([readonly]) + label {
+ color: {{hexcolor}} !important;
+ }
+
input[type=text]:focus, .materialize-textarea:focus:not([readonly]) {
border-bottom: 1px solid {{hexcolor}} !important;
box-shadow: 0 1px 0 0 {{hexcolor}} !important;
diff --git a/templates/registration/login.html b/templates/registration/login.html
index 8a2b258..cfa4a2b 100644
--- a/templates/registration/login.html
+++ b/templates/registration/login.html
@@ -19,7 +19,7 @@
<br><br><hr><br>
<div class="row">
<div class="col s12">
- <a href={% url 'oauth_login' %} style="width: 100%; background-color: #99BF62" class="btn waves-effect waves-light">
+ <a href="{% url 'oauth_login' %}?next={{ request.GET.next }}" style="width: 100%; background-color: #99BF62" class="btn waves-effect waves-light">
<div class="row">
<div class="col s2">
<img style="height: 30px; padding-top: 3px" src="{% static 'pbs_logo.svg' %}" alt="PBS Logo">
diff --git a/version.txt b/version.txt
index 7c0c6a3..2058a6b 100644
--- a/version.txt
+++ b/version.txt
@@ -1,2 +1,2 @@
version=0.4
-rev=13
+rev=14