Skip to content
Snippets Groups Projects

Improve automatic emails with temporary urls

Merged Flavio TARSETTI requested to merge 542_temporary_urls into master
1 file
+ 149
1
Compare changes
  • Side-by-side
  • Inline
+ 347
39
@@ -25,19 +25,32 @@
# #
###############################################################################
from django.conf import settings
from django.shortcuts import render
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import PasswordChangeForm
from django.contrib.auth.models import User
from django.contrib import messages
from django.db import models
from django.db.models import Q
from rest_framework.authtoken.models import Token
from .forms import AccountSettingsForm
from .models import AccountSettings
from .models import SupervisionTrack, Profile
from .models import SupervisionTrack
from .models import Profile
from .models import TemporaryUrl
from ..utils import mail
import datetime
from urllib.parse import urlparse
@login_required
def account_settings(request):
@@ -47,23 +60,32 @@ def account_settings(request):
user = request.user
password_change_form = PasswordChangeForm(user=user)
if request.method == 'POST':
if 'password' in request.POST:
if request.method == "POST":
if "password" in request.POST:
password_change_form = PasswordChangeForm(data=request.POST, user=user)
if password_change_form.is_valid():
password_change_form.save()
messages.add_message(request, messages.SUCCESS, 'Password changed successfully')
messages.add_message(
request, messages.SUCCESS, "Password changed successfully"
)
elif 'token' in request.POST:
elif "token" in request.POST:
user.auth_token.delete()
Token.objects.create(user=user)
messages.add_message(request, messages.SUCCESS, 'Token changed successfully')
messages.add_message(
request, messages.SUCCESS, "Token changed successfully"
)
else: #'settings'
account_settings_form = AccountSettingsForm(data=request.POST, instance=account_settings)
else:
# "settings"
account_settings_form = AccountSettingsForm(
data=request.POST, instance=account_settings
)
if account_settings_form.is_valid():
account_settings_form.save()
messages.add_message(request, messages.SUCCESS, 'Account settings changed successfully')
account_settings_form.save()
messages.add_message(
request, messages.SUCCESS, "Account settings changed successfully"
)
else:
account_settings_form = AccountSettingsForm(instance=account_settings)
@@ -75,42 +97,328 @@ def account_settings(request):
supervisors_valid = None
supervisors_pending = None
supervisiontracks_supervisors_valid = None
if user.profile.is_supervisor == False and not user.is_superuser:
if not user.profile.is_supervisor and not user.is_superuser:
supervisee = user
if supervisee.profile.supervision_key is not None:
#There's a key check if there's a valid track
supervisiontrack = SupervisionTrack.objects.get(supervisee=supervisee, supervisee__profile__supervision_key=models.F('supervision_key'))
# There's a key check if there's a valid track
supervisiontrack = SupervisionTrack.objects.get(
supervisee=supervisee,
supervisee__profile__supervision_key=models.F("supervision_key"),
)
else:
supervisiontrack = None
elif user.profile.is_supervisor and not user.is_superuser:
supervisor = user
#Filter and get all supervision tracks valid and
supervisiontracks_valid = SupervisionTrack.objects.filter(supervisor=supervisor, is_valid=True)
supervisiontracks_pending = SupervisionTrack.objects.filter(supervisor=supervisor, is_valid=False, start_date=None).exclude(supervisee__profile__status=Profile.NEWUSER)
# Filter and get all supervision tracks valid and
supervisiontracks_valid = SupervisionTrack.objects.filter(
supervisor=supervisor, is_valid=True
)
supervisiontracks_pending = SupervisionTrack.objects.filter(
supervisor=supervisor, is_valid=False, start_date=None
).exclude(supervisee__profile__status=Profile.NEWUSER)
if supervisor.profile.supervision_key is not None:
#There's a key check if there's a valid track
supervisiontrack = SupervisionTrack.objects.get(supervisee=supervisor, supervisee__profile__supervision_key=models.F('supervision_key'))
# There's a key check if there's a valid track
supervisiontrack = SupervisionTrack.objects.get(
supervisee=supervisor,
supervisee__profile__supervision_key=models.F("supervision_key"),
)
else:
supervisiontrack = None
else:
supervisor = user
#Filter and get all supervision tracks valid and pending
supervisiontracks_valid = SupervisionTrack.objects.filter(supervisor=supervisor, is_valid=True, supervisee__profile__is_supervisor=False)
supervisiontracks_pending = SupervisionTrack.objects.filter(supervisor=supervisor, is_valid=False, start_date=None, supervisee__profile__is_supervisor=False).exclude(supervisee__profile__status=Profile.NEWUSER)
#Get all new supervisor accounts pending requests and valid
supervisors_valid = User.objects.filter(profile__is_supervisor=True, profile__status=Profile.ACCEPTED, is_superuser=False)
supervisiontracks_supervisors_valid = SupervisionTrack.objects.filter(supervisee__profile__is_supervisor=True, is_valid=True)
supervisors_pending = User.objects.filter(profile__is_supervisor=True, profile__status=Profile.WAITINGVALIDATION, is_superuser=False)
return render(request,
'accounts/settings.html',
{'account_settings_form': account_settings_form,
'password_change_form': password_change_form,
'user': user,
'supervisiontrack': supervisiontrack,
'supervisiontracks_valid': supervisiontracks_valid,
'supervisiontracks_pending': supervisiontracks_pending,
'supervisiontracks_supervisors_valid': supervisiontracks_supervisors_valid,
'supervisors_valid': supervisors_valid,
'supervisors_pending': supervisors_pending,
'token' : user.auth_token})
# Filter and get all supervision tracks valid and pending
supervisiontracks_valid = SupervisionTrack.objects.filter(
supervisor=supervisor,
is_valid=True,
supervisee__profile__is_supervisor=False,
)
supervisiontracks_pending = SupervisionTrack.objects.filter(
supervisor=supervisor,
is_valid=False,
start_date=None,
supervisee__profile__is_supervisor=False,
).exclude(supervisee__profile__status=Profile.NEWUSER)
# Get all new supervisor accounts pending requests and valid
supervisors_valid = User.objects.filter(
profile__is_supervisor=True,
profile__status=Profile.ACCEPTED,
is_superuser=False,
)
supervisiontracks_supervisors_valid = SupervisionTrack.objects.filter(
supervisee__profile__is_supervisor=True, is_valid=True
)
supervisors_pending = User.objects.filter(
profile__is_supervisor=True,
profile__status=Profile.WAITINGVALIDATION,
is_superuser=False,
)
return render(
request,
"accounts/settings.html",
{
"account_settings_form": account_settings_form,
"password_change_form": password_change_form,
"user": user,
"supervisiontrack": supervisiontrack,
"supervisiontracks_valid": supervisiontracks_valid,
"supervisiontracks_pending": supervisiontracks_pending,
"supervisiontracks_supervisors_valid": supervisiontracks_supervisors_valid,
"supervisors_valid": supervisors_valid,
"supervisors_pending": supervisors_pending,
"token": user.auth_token,
},
)
def emergency_rejection(request, supervisee):
# No key is present in supervisee
# Make sure all tracks are invalid
supervisiontracks = SupervisionTrack.objects.filter(
supervisee=supervisee, is_valid=True
)
# This should never be the case but if it happens invalidate all tracks
if supervisiontracks.count() > 0:
now = datetime.datetime.now()
for track in supervisiontracks:
track.is_valid = False
track.expiration_date = now
track.save()
# Not allowed to do this (unproper profile.status)
error_message = "You are not allowed to perform this action, you first need to get a valid supervision"
return error_message
def supervisee_rejection(supervisiontrack, supervisee, now):
expiration_date_delta = datetime.timedelta(
days=settings.ACCOUNT_BLOCKAGE_AFTER_FIRST_REJECTION_DAYS
)
supervisiontrack.expiration_date = now
supervisiontrack.is_valid = False
if supervisee.profile.status != Profile.BLOCKED:
supervisee.profile.status = Profile.REJECTED
if supervisee.profile.rejection_date is None:
supervisee.profile.rejection_date = now + expiration_date_delta
else:
supervisee.profile.rejection_date = None
supervisee.profile.supervision_key = None
supervisiontrack.save()
supervisee.profile.save()
supervisee.save()
def perform_revalidation(request, supervisiontrack, supervisee, now):
success = False
error_message = None
if supervisiontrack.is_valid:
if supervisee.profile.status == Profile.YEARREVALIDATION:
# Check Supervisor validity
supervisor = supervisiontrack.supervisor
# If Supervisor account is not valid. Reject the account (though this should already be done during supervisor rejection)
if supervisor.profile.status != Profile.BLOCKED:
# Change status
supervisee.profile.status = Profile.ACCEPTED
# Extend supervisiontrack validity for another 12 months
expiration_date_delta = datetime.timedelta(
days=settings.ACCOUNT_EXPIRATION_DAYS
)
new_expiration_date = (
supervisiontrack.expiration_date + expiration_date_delta
)
supervisiontrack.expiration_date = new_expiration_date
supervisiontrack.last_validation_date = now
else:
# Change status
expiration_date_delta = datetime.timedelta(
days=settings.ACCOUNT_BLOCKAGE_AFTER_FIRST_REJECTION_DAYS
)
supervisiontrack.expiration_date = now
supervisiontrack.is_valid = False
supervisee.profile.status = Profile.REJECTED
supervisee.profile.rejection_date = now + expiration_date_delta
supervisee.profile.supervision_key = None
# save
supervisiontrack.save()
supervisee.profile.save()
supervisee.save()
# Inform supervisor about supervisee revalidation
# Possible supervisor rejection available
parsed_url = urlparse(settings.URL_PREFIX)
server_address = "%s://%s" % (parsed_url.scheme, parsed_url.hostname,)
temp_url_rejection = TemporaryUrl.objects.create_temporary_url(
TemporaryUrl.REJECTION, supervisiontrack
)
context = {
"supervisor": supervisiontrack.supervisor,
"supervisee": supervisee,
"prefix": server_address,
"temp_url": temp_url_rejection.url_hash,
}
mail.send_email(
"registration/mail.account_revalidation_supervisor.subject.txt",
"registration/mail.supervisor_possible_supervisee_rejection.message.txt",
context,
[supervisiontrack.supervisor.email],
)
success = True
return (success, error_message)
else:
# Track already valid
error_message = "You don't need to revalidate at the moment, your supervision is still valid"
return (success, error_message)
else:
# A pending request already exist
error_message = "You are not able to perform this action as you already have a pending supervision request"
return (success, error_message)
def accept_supervisee(supervisiontrack, supervisee, now):
supervisiontrack.is_valid = True
expiration_date_delta = datetime.timedelta(days=settings.ACCOUNT_EXPIRATION_DAYS)
supervisiontrack.expiration_date = now + expiration_date_delta
supervisiontrack.start_date = now
supervisiontrack.last_validation_date = now
supervisee.profile.status = Profile.ACCEPTED
supervisee.profile.rejection_date = None
supervisiontrack.save()
supervisee.profile.save()
supervisee.is_active = True
supervisee.save()
parsed_url = urlparse(settings.URL_PREFIX)
server_address = "%s://%s" % (parsed_url.scheme, parsed_url.hostname)
context = {
"supervisor": supervisiontrack.supervisor,
"supervisee": supervisee,
"prefix": server_address,
}
mail.send_email(
"registration/mail.supervisor_validated.subject.txt",
"registration/mail.supervisor_validated.message.txt",
context,
[supervisee.email],
)
def generate_load_response(request, temp_url, template, parameters):
answer = {}
answer["template"] = template
answer["parameters"] = parameters
temp_url.delete()
return render(request, answer["template"], answer["parameters"])
def load_temporary_url_validation(request, hash_url):
temp_url = get_object_or_404(TemporaryUrl, url_hash=hash_url)
supervisiontrack = temp_url.supervision_track
supervisee = supervisiontrack.supervisee
now = datetime.datetime.now()
if temp_url.status == TemporaryUrl.VALIDATION:
# Supervisor validates new Supervisee
if supervisee.profile.status != Profile.ACCEPTED and now < temp_url.expires:
accept_supervisee(supervisiontrack, supervisee, now)
return generate_load_response(
request,
temp_url,
"accounts/url_validation.html",
{"supervisiontrack": supervisiontrack},
)
else:
# Track already valid
return generate_load_response(
request, temp_url, "accounts/url_validation_failed.html", {}
)
elif temp_url.status == TemporaryUrl.YEARREVALIDATION:
# Supervisee re-validation
if supervisee.profile.supervision_key is not None and now < temp_url.expires:
success, error_message = perform_revalidation(
request, supervisiontrack, supervisee, now
)
if not success:
return generate_load_response(
request,
temp_url,
"accounts/url_revalidation_failed.html",
{"error_message": error_message},
)
else:
error_message = emergency_rejection(request, supervisee)
return generate_load_response(
request,
temp_url,
"accounts/url_revalidation_failed.html",
{"error_message": error_message},
)
return generate_load_response(
request,
temp_url,
"accounts/url_validation.html",
{"supervisiontrack": supervisiontrack},
)
else:
# Track already valid
return generate_load_response(
request, temp_url, "accounts/url_validation_failed.html", {}
)
def load_temporary_url_rejection(request, hash_url):
temp_url = get_object_or_404(TemporaryUrl, url_hash=hash_url)
supervisiontrack = temp_url.supervision_track
supervisee = supervisiontrack.supervisee
parsed_url = urlparse(settings.URL_PREFIX)
server_address = "%s://%s" % (parsed_url.scheme, parsed_url.hostname)
context = {
"supervisor": supervisiontrack.supervisor,
"supervisee": supervisee,
"prefix": server_address,
}
now = datetime.datetime.now()
if temp_url.status == TemporaryUrl.REJECTION:
# Supervisor rejects Supervisee
if supervisee.profile.supervision_key is not None and now < temp_url.expires:
if supervisiontrack.is_valid:
supervisee_rejection(supervisiontrack, supervisee, now)
mail.send_email(
"registration/mail.supervisor_rejected.subject.txt",
"registration/mail.supervisor_rejected.message.txt",
context,
[supervisee.email],
)
return generate_load_response(
request,
temp_url,
"accounts/url_rejection.html",
{"supervisiontrack": supervisiontrack},
)
return generate_load_response(
request, temp_url, "accounts/url_rejection_failed.html", {}
)
Loading