Commit 21f6401a authored by Samuel GAIST's avatar Samuel GAIST

Merge branch '542_temporary_urls' into 'master'

Improve automatic emails with temporary urls

Closes #550 and #542

See merge request !328
parents a6edb816 0d34343a
Pipeline #39926 passed with stages
in 16 minutes and 38 seconds
This diff is collapsed.
#!/usr/bin/env python
# vim: set fileencoding=utf-8 :
# encoding: utf-8
###############################################################################
# #
# Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/ #
# Contact: beat.support@idiap.ch #
# #
# This file is part of the beat.web module of the BEAT platform. #
# #
# Commercial License Usage #
# Licensees holding valid commercial BEAT licenses may use this file in #
# accordance with the terms contained in a written agreement between you #
# and Idiap. For further information contact tto@idiap.ch #
# #
# Alternatively, this file may be used under the terms of the GNU Affero #
# Public License version 3 as published by the Free Software and appearing #
# in the file LICENSE.AGPL included in the packaging of this file. #
# The BEAT platform is distributed in the hope that it will be useful, but #
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY #
# or FITNESS FOR A PARTICULAR PURPOSE. #
# #
# You should have received a copy of the GNU Affero Public License along #
# with the BEAT platform. If not, see http://www.gnu.org/licenses/. #
# #
###############################################################################
from django.core.management.base import BaseCommand
import datetime
import sys
from ...models import TemporaryUrl
class Command(BaseCommand):
help = 'Clean expired temporary urls'
def add_arguments(self, parser):
parser.add_argument('--noinput', action='store_false', dest='interactive', default=False,
help=('Tells Django to NOT prompt the user for input of any kind.'))
def handle(self, *args, **options):
if options['interactive']:
try:
answer = self.get_input_data('Clean expired temporary url(s) that have not been used? (y/n)? ', 'y').lower()
except KeyboardInterrupt:
self.stderr.write("\nOperation canceled.")
sys.exit(1)
if answer != 'y':
self.stdout.write('Clean expired temporary urls operation canceled')
sys.exit(1)
temporary_urls_count = TemporaryUrl.objects.all().count()
now = datetime.datetime.now()
count, _ = TemporaryUrl.objects.filter(expires__lt=now).delete()
self.stdout.write('{} Expired temporary url(s) successfully cleaned/'.format(count) + '{} Total temporary url(s) checked'.format(temporary_urls_count))
def get_input_data(self, message, default=None):
"""
Override this method if you want to customize data inputs or
validation exceptions.
"""
raw_value = raw_input(message)
if default and raw_value == '':
raw_value = default
return raw_value
......@@ -40,6 +40,7 @@ from django.template import loader
from ...models import SupervisionTrack
from ...models import Profile
from ...models import TemporaryUrl
from ....ui.registration.models import RegistrationProfile
from ....utils import mail
......@@ -210,9 +211,13 @@ class Command(BaseCommand):
if supervisiontrack.expiration_date.date() - now.date() == datetime.timedelta(days=expiration_reminder):
warned_count += 1
temp_url = TemporaryUrl.objects.create_temporary_url(TemporaryUrl.YEARREVALIDATION, supervisiontrack)
context = {
'user': user,
'expiration_date': supervisiontrack.expiration_date.date(),
"prefix": server_address,
"temp_url": temp_url.url_hash,
}
mail.send_email('registration/mail.account_revalidation.subject.txt',
......
# -*- coding: utf-8 -*-
# Generated by Django 1.11.26 on 2020-05-02 03:02
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
("accounts", "0011_check_all_accounts"),
]
operations = [
migrations.CreateModel(
name="TemporaryUrl",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
(
"status",
models.CharField(
choices=[
("V", "Supervisor validates supervisee"),
("Y", "Self yearly revalidation from supervisee"),
],
default="V",
max_length=1,
),
),
(
"url_hash",
models.CharField(max_length=32, unique=True, verbose_name="Url"),
),
("expires", models.DateTimeField(verbose_name="Expires")),
(
"supervision_track",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="supervisees",
to="accounts.SupervisionTrack",
),
),
],
),
migrations.AlterField(
model_name="profile",
name="status",
field=models.CharField(
choices=[
("N", "New User"),
("W", "Waiting Validation"),
("A", "Accepted"),
("R", "Rejected"),
("Y", "Yearly revalidation"),
("B", "Blocked no supervisor"),
],
default="B",
max_length=1,
),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.11.26 on 2020-05-13 18:48
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("accounts", "0012_accounts_temporary_url"),
]
operations = [
migrations.AlterField(
model_name="temporaryurl",
name="status",
field=models.CharField(
choices=[
("V", "Supervisor validates supervisee"),
("Y", "Self yearly revalidation from supervisee"),
("R", "Supervisor rejects supervisee revalidation"),
],
default="V",
max_length=1,
),
),
]
......@@ -29,9 +29,18 @@ from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
import random
import string
import datetime
# ------------------------------------------------------------------------------
# Constants
TEMPORARY_URL_LENGTH = 32
# ------------------------------------------------------------------------------
class AccountSettingsManager(models.Manager):
......@@ -149,3 +158,64 @@ def create_user_profile(sender, instance, created, **kwargs):
def save_user_profile(sender, instance, **kwargs):
player, created = Profile.objects.get_or_create(user=instance)
instance.profile.save()
def generate_url_hash():
# url_hash creation
url_hash = "".join(
random.choice(string.ascii_letters + string.digits) # nosec
for _ in range(TEMPORARY_URL_LENGTH)
)
return url_hash
class TemporaryUrlManager(models.Manager):
def create_temporary_url(self, status, supervision_track):
# Actions that result creating the object
url_hash = generate_url_hash()
used_hashes = [x.url_hash for x in TemporaryUrl.objects.all()]
while url_hash in used_hashes:
url_hash = generate_url_hash()
now = datetime.datetime.now()
expiration_date_delta = datetime.timedelta(
days=settings.ACCOUNT_ACTIVATION_DAYS_FROM_SUPERVISOR
)
expires = now + expiration_date_delta
temporary_url = self.model(
status=status,
url_hash=url_hash,
expires=expires,
supervision_track=supervision_track,
)
temporary_url.save()
return temporary_url
class TemporaryUrl(models.Model):
# _____ Constants __________
# Supervisor validates supervisee
# Self yearly revalidation from supervisee
VALIDATION = "V"
YEARREVALIDATION = "Y"
REJECTION = "R"
URL_STATUS = (
(VALIDATION, "Supervisor validates supervisee"),
(YEARREVALIDATION, "Self yearly revalidation from supervisee"),
(REJECTION, "Supervisor rejects supervisee revalidation"),
)
# _____ Fields __________
status = models.CharField(max_length=1, choices=URL_STATUS, default=VALIDATION)
url_hash = models.CharField("Url", blank=False, max_length=32, unique=True)
expires = models.DateTimeField("Expires")
supervision_track = models.ForeignKey(
SupervisionTrack, on_delete=models.CASCADE, related_name="supervisees"
)
objects = TemporaryUrlManager()
{% extends "base.html" %}
{% comment %}
* Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
{% load fingerprint %}
{% load ui_tags %}
{% load gravatar %}
{% load registration_tags %}
{% load account_tags %}
{% block title %}As requested, the supervision from {{supervisiontrack.supervisor.username}} for {{supervisiontrack.supervisee.username}} is revoked!{% endblock %}
{% block stylesheets %}
{{ block.super }}
<link rel="stylesheet" href="{% fingerprint "accounts/css/dialogs.css" %}" type="text/css" media="screen" />
<link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
<link href="{% fingerprint "/bootstrap-toggle/css/bootstrap-toggle.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
{% endblock %}
{% block scripts %}
{{ block.super }}
{% csrf_token %}
<script src="{% fingerprint "bootstrap3-typeahead/bootstrap3-typeahead.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "accounts/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.core.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.position.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.widget.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.button.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.dialog.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
{% with 48 as width %}
<h3 class="page-title"><img class="img-circle" width="{{ width }}" height="{{ width }}" data-toggle="tooltip" data-placement="top" title="To change your avatar, visit http://gravatar.com"></img> As requested, the supervision from {{supervisiontrack.supervisor.username}} for {{supervisiontrack.supervisee.username}} is revoked!</h3>
{% endwith %}
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% comment %}
* Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
{% load fingerprint %}
{% load ui_tags %}
{% load gravatar %}
{% load registration_tags %}
{% load account_tags %}
{% block title %}A failure occured for the rejection of this supervisee. Please contact an admin.{% endblock %}
{% block stylesheets %}
{{ block.super }}
<link rel="stylesheet" href="{% fingerprint "accounts/css/dialogs.css" %}" type="text/css" media="screen" />
<link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
<link href="{% fingerprint "/bootstrap-toggle/css/bootstrap-toggle.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
{% endblock %}
{% block scripts %}
{{ block.super }}
{% csrf_token %}
<script src="{% fingerprint "bootstrap3-typeahead/bootstrap3-typeahead.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "accounts/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.core.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.position.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.widget.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.button.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.dialog.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
{% with 48 as width %}
<h3 class="page-title"><img class="img-circle" width="{{ width }}" height="{{ width }}" data-toggle="tooltip" data-placement="top" title="To change your avatar, visit http://gravatar.com"></img>A failure occured for the rejection of this supervisee. Please contact an admin.</h3>
{% endwith %}
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% comment %}
* Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
{% load fingerprint %}
{% load ui_tags %}
{% load gravatar %}
{% load registration_tags %}
{% load account_tags %}
{% block title %}{{error_message}}{% endblock %}
{% block stylesheets %}
{{ block.super }}
<link rel="stylesheet" href="{% fingerprint "accounts/css/dialogs.css" %}" type="text/css" media="screen" />
<link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
<link href="{% fingerprint "/bootstrap-toggle/css/bootstrap-toggle.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
{% endblock %}
{% block scripts %}
{{ block.super }}
{% csrf_token %}
<script src="{% fingerprint "bootstrap3-typeahead/bootstrap3-typeahead.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "accounts/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.core.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.position.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.widget.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.button.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.dialog.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
{% with 48 as width %}
<h3 class="page-title"><img class="img-circle" width="{{ width }}" height="{{ width }}" data-toggle="tooltip" data-placement="top" title="To change your avatar, visit http://gravatar.com"></img>{{error_message}}</h3>
{% endwith %}
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% comment %}
* Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
{% load fingerprint %}
{% load ui_tags %}
{% load gravatar %}
{% load registration_tags %}
{% load account_tags %}
{% block title %}Congratulations, the supervision from {{supervisiontrack.supervisor.username}} for {{supervisiontrack.supervisee.username}} is now valid!{% endblock %}
{% block stylesheets %}
{{ block.super }}
<link rel="stylesheet" href="{% fingerprint "accounts/css/dialogs.css" %}" type="text/css" media="screen" />
<link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
<link href="{% fingerprint "/bootstrap-toggle/css/bootstrap-toggle.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
{% endblock %}
{% block scripts %}
{{ block.super }}
{% csrf_token %}
<script src="{% fingerprint "bootstrap3-typeahead/bootstrap3-typeahead.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "accounts/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.core.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.position.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.widget.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.button.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.dialog.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
{% with 48 as width %}
<h3 class="page-title"><img class="img-circle" width="{{ width }}" height="{{ width }}" data-toggle="tooltip" data-placement="top" title="To change your avatar, visit http://gravatar.com"></img> Congratulations, the supervision from {{supervisiontrack.supervisor.username}} for {{supervisiontrack.supervisee.username}} is now valid!</h3>
{% endwith %}
</div>
</div>
{% endblock %}
{% extends "base.html" %}
{% comment %}
* Copyright (c) 2020 Idiap Research Institute, http://www.idiap.ch/
* Contact: beat.support@idiap.ch
*
* This file is part of the beat.web module of the BEAT platform.
*
* Commercial License Usage
* Licensees holding valid commercial BEAT licenses may use this file in
* accordance with the terms contained in a written agreement between you
* and Idiap. For further information contact tto@idiap.ch
*
* Alternatively, this file may be used under the terms of the GNU Affero
* Public License version 3 as published by the Free Software and appearing
* in the file LICENSE.AGPL included in the packaging of this file.
* The BEAT platform is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* You should have received a copy of the GNU Affero Public License along
* with the BEAT platform. If not, see http://www.gnu.org/licenses/.
{% endcomment %}
{% load fingerprint %}
{% load ui_tags %}
{% load gravatar %}
{% load registration_tags %}
{% load account_tags %}
{% block title %}You can't validate this supervisee!{% endblock %}
{% block stylesheets %}
{{ block.super }}
<link rel="stylesheet" href="{% fingerprint "accounts/css/dialogs.css" %}" type="text/css" media="screen" />
<link rel="stylesheet" href="{% fingerprint "jquery-ui/themes/base/minified/jquery-ui.min.css" %}" type="text/css" media="screen" />
<link href="{% fingerprint "/bootstrap-toggle/css/bootstrap-toggle.min.css" %}" rel="stylesheet">
<link rel="stylesheet" href="{% fingerprint "datatables/media/css/dataTables.bootstrap.min.css" %}" type="text/css" media="screen" />
{% endblock %}
{% block scripts %}
{{ block.super }}
{% csrf_token %}
<script src="{% fingerprint "bootstrap3-typeahead/bootstrap3-typeahead.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "accounts/js/dialogs.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.core.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.position.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.widget.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.button.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="{% fingerprint "jquery-ui/ui/minified/jquery.ui.dialog.min.js" %}" type="text/javascript" charset="utf-8"></script>
<script src="https://gitcdn.github.io/bootstrap-toggle/2.2.2/js/bootstrap-toggle.min.js"></script>
{% endblock %}
{% block content %}
<div class="row">
<div class="col-sm-6 col-sm-offset-3">
{% with 48 as width %}
<h3 class="page-title"><img class="img-circle" width="{{ width }}" height="{{ width }}" data-toggle="tooltip" data-placement="top" title="To change your avatar, visit http://gravatar.com"></img>You can't validate this supervisee!</h3>
{% endwith %}
</div>
</div>
{% endblock %}
This diff is collapsed.
......@@ -29,5 +29,15 @@ from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^settings/$', views.account_settings, name='settings'),
url(r"^settings/$", views.account_settings, name="settings"),
url(
r"^validation/(?P<hash_url>\w+)/$",
views.load_temporary_url_validation,
name="temp_url_validation",
),
url(
r"^rejection/(?P<hash_url>\w+)/$",
views.load_temporary_url_rejection,
name="temp_url_rejection",
),
]
This diff is collapsed.
......@@ -33,51 +33,54 @@ from .models import Agreement
from ..accounts.models import AccountSettings
from ..accounts.models import SupervisionTrack
from ..accounts.models import Profile
from ..accounts.models import TemporaryUrl
#----------------------------------------------------------
# ----------------------------------------------------------
class AgreementInline(admin.StackedInline):
model = Agreement
#----------------------------------------------------------
# ----------------------------------------------------------
class AccountSettingsInline(admin.StackedInline):
model = AccountSettings
#----------------------------------------------------------
# ----------------------------------------------------------
class SupervisionTrackInline(admin.StackedInline):
model = SupervisionTrack
fk_name = 'supervisor'
fk_name = "supervisor"
#----------------------------------------------------------
# ----------------------------------------------------------
class ProfileInline(admin.StackedInline):
model = Profile
#----------------------------------------------------------
# ----------------------------------------------------------
class UserAdmin(UserAdmin):