diff --git a/apps/registration/forms.py b/apps/registration/forms.py index ae519f0..3282cd7 100644 --- a/apps/registration/forms.py +++ b/apps/registration/forms.py @@ -1,6 +1,7 @@ from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User +from django.core.exceptions import ValidationError from django.utils.translation import gettext_lazy as _ from .models import AdminRegistration, CoachRegistration, StudentRegistration @@ -44,6 +45,18 @@ class StudentRegistrationForm(forms.ModelForm): fields = ('student_class', 'school', 'give_contact_to_animath',) +class PhotoAuthorizationForm(forms.ModelForm): + def clean_photo_authorization(self): + file = self.files["photo_authorization"] + if file.content_type not in ["application/pdf", "image/png", "image/jpeg"]: + raise ValidationError(_("The uploaded file must be a PDF, PNG of JPEG file.")) + return self.cleaned_data["photo_authorization"] + + class Meta: + model = StudentRegistration + fields = ('photo_authorization',) + + class CoachRegistrationForm(forms.ModelForm): class Meta: model = CoachRegistration diff --git a/apps/registration/migrations/0004_studentregistration_photo_authorization.py b/apps/registration/migrations/0004_studentregistration_photo_authorization.py new file mode 100644 index 0000000..c6477ee --- /dev/null +++ b/apps/registration/migrations/0004_studentregistration_photo_authorization.py @@ -0,0 +1,19 @@ +# Generated by Django 3.1.1 on 2020-09-24 20:36 + +from django.db import migrations, models +import registration.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('registration', '0003_registration_email_confirmed'), + ] + + operations = [ + migrations.AddField( + model_name='studentregistration', + name='photo_authorization', + field=models.FileField(blank=True, default='', upload_to=registration.models.get_random_filename, verbose_name='photo authorization'), + ), + ] diff --git a/apps/registration/models.py b/apps/registration/models.py index e2dcc05..fa584df 100644 --- a/apps/registration/models.py +++ b/apps/registration/models.py @@ -2,6 +2,7 @@ from corres2math.tokens import email_validation_token from django.contrib.sites.models import Site from django.db import models from django.template import loader +from django.utils.crypto import get_random_string from django.utils.encoding import force_bytes from django.utils.http import urlsafe_base64_encode from django.utils.translation import gettext_lazy as _ @@ -66,6 +67,10 @@ class Registration(PolymorphicModel): verbose_name_plural = _("registrations") +def get_random_filename(instance, filename): + return get_random_string(64) + + class StudentRegistration(Registration): team = models.ForeignKey( "participation.Team", @@ -90,6 +95,14 @@ class StudentRegistration(Registration): verbose_name=_("school"), ) + # FIXME Fix permission access, mime type + photo_authorization = models.FileField( + verbose_name=_("photo authorization"), + upload_to=get_random_filename, + blank=True, + default="", + ) + @property def type(self): return _("student") diff --git a/apps/registration/templates/registration/upload_photo_authorization.html b/apps/registration/templates/registration/upload_photo_authorization.html new file mode 100644 index 0000000..f673865 --- /dev/null +++ b/apps/registration/templates/registration/upload_photo_authorization.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% load i18n crispy_forms_filters %} + +{% block content %} +
+
+ {% csrf_token %} + {{ form|crispy }} +
+ +
+{% endblock %} diff --git a/apps/registration/templates/registration/user_detail.html b/apps/registration/templates/registration/user_detail.html index 714e242..9ed7bb3 100644 --- a/apps/registration/templates/registration/user_detail.html +++ b/apps/registration/templates/registration/user_detail.html @@ -27,6 +27,13 @@
{% trans "School:" %}
{{ user_object.registration.school }}
+ +
{% trans "Photo authorization:" %}
+
+ {% if user_object.registration.photo_authorization %} + {% trans "Download" %} + {% endif %} +
{% elif user_object.registration.coachregistration %}
{% trans "Profesional activity:" %}
{{ user_object.registration.professional_activity }}
@@ -44,11 +51,15 @@ - {% trans "Update user" as modal_title %} {% trans "Update" as modal_button %} {% url "registration:update_user" pk=user_object.pk as modal_action %} {% include "base_modal.html" with modal_id="updateUser" %} + + {% trans "Upload photo authorization" as modal_title %} + {% trans "Upload" as modal_button %} + {% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk as modal_action %} + {% include "base_modal.html" with modal_id="uploadPhotoAuthorization" modal_enctype="multipart/form-data" %} {% endblock %} {% block extrajavascript %} @@ -59,6 +70,11 @@ if (!modalBody.html().trim()) modalBody.load("{% url "registration:update_user" pk=user_object.pk %} #form-content"); }); + $('button[data-target="#uploadPhotoAuthorizationModal"]').click(function() { + let modalBody = $("#uploadPhotoAuthorizationModal div.modal-body"); + if (!modalBody.html().trim()) + modalBody.load("{% url "registration:upload_user_photo_authorization" pk=user_object.registration.pk %} #form-content"); + }); }); {% endblock %} diff --git a/apps/registration/urls.py b/apps/registration/urls.py index 7bd4d95..76e2461 100644 --- a/apps/registration/urls.py +++ b/apps/registration/urls.py @@ -1,7 +1,7 @@ from django.urls import path -from .views import MyAccountDetailView, SignupView, UserDetailView, UserResendValidationEmailView, UserUpdateView,\ - UserValidateView, UserValidationEmailSentView +from .views import MyAccountDetailView, SignupView, UserDetailView, UserResendValidationEmailView,\ + UserUpdateView, UserUploadPhotoAuthorizationView, UserValidateView, UserValidationEmailSentView app_name = "registration" @@ -14,4 +14,6 @@ urlpatterns = [ path("user/", MyAccountDetailView.as_view(), name="my_account_detail"), path("user//", UserDetailView.as_view(), name="user_detail"), path("user//update/", UserUpdateView.as_view(), name="update_user"), + path("user//upload-photo-authorization/", UserUploadPhotoAuthorizationView.as_view(), + name="upload_user_photo_authorization"), ] diff --git a/apps/registration/views.py b/apps/registration/views.py index dc8ccd8..103c9c1 100644 --- a/apps/registration/views.py +++ b/apps/registration/views.py @@ -10,7 +10,8 @@ from django.utils.http import urlsafe_base64_decode from django.utils.translation import gettext_lazy as _ from django.views.generic import CreateView, DetailView, RedirectView, TemplateView, UpdateView -from .forms import CoachRegistrationForm, SignupForm, StudentRegistrationForm, UserForm +from .forms import CoachRegistrationForm, PhotoAuthorizationForm, SignupForm, StudentRegistrationForm, UserForm +from .models import StudentRegistration class SignupView(CreateView): @@ -156,3 +157,12 @@ class UserUpdateView(LoginRequiredMixin, UpdateView): def get_success_url(self): return reverse_lazy("registration:user_detail", args=(self.object.pk,)) + + +class UserUploadPhotoAuthorizationView(LoginRequiredMixin, UpdateView): + model = StudentRegistration + form_class = PhotoAuthorizationForm + template_name = "registration/upload_photo_authorization.html" + + def get_success_url(self): + return reverse_lazy("registration:user_detail", args=(self.object.user.pk,)) diff --git a/corres2math/static/Autorisation de droit à l'image - majeur.pdf b/corres2math/static/Autorisation de droit à l'image - majeur.pdf new file mode 100644 index 0000000..b6d8d98 Binary files /dev/null and b/corres2math/static/Autorisation de droit à l'image - majeur.pdf differ diff --git a/corres2math/static/Autorisation de droit à l'image - mineur.pdf b/corres2math/static/Autorisation de droit à l'image - mineur.pdf new file mode 100644 index 0000000..ea380cb Binary files /dev/null and b/corres2math/static/Autorisation de droit à l'image - mineur.pdf differ diff --git a/corres2math/urls.py b/corres2math/urls.py index b7b6e3a..0aca2ec 100644 --- a/corres2math/urls.py +++ b/corres2math/urls.py @@ -13,12 +13,14 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ - +from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include from django.views.defaults import bad_request, permission_denied, page_not_found, server_error from django.views.generic import TemplateView +from corres2math import settings + urlpatterns = [ path('', TemplateView.as_view(template_name="index.html"), name='index'), path('i18n/', include('django.conf.urls.i18n')), @@ -33,6 +35,9 @@ urlpatterns = [ path('', include('eastereggs.urls')), ] +# FIXME Protect files +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) + handler400 = bad_request handler403 = permission_denied handler404 = page_not_found diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 5a46299..7ce3b51 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: Corres2math\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-09-24 21:42+0200\n" +"POT-Creation-Date: 2020-09-24 22:01+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: LANGUAGE \n" @@ -38,7 +38,7 @@ msgstr "Fermer" msgid "Logs" msgstr "Logs" -#: apps/logs/models.py:22 apps/registration/models.py:17 +#: apps/logs/models.py:22 apps/registration/models.py:15 msgid "user" msgstr "utilisateur" @@ -141,7 +141,7 @@ msgid "Team {name} ({trigram})" msgstr "Équipe {name} ({trigram})" #: apps/participation/models.py:45 apps/participation/models.py:56 -#: apps/registration/models.py:78 apps/registration/models.py:123 +#: apps/registration/models.py:76 apps/registration/models.py:121 msgid "team" msgstr "équipe" @@ -259,8 +259,8 @@ msgstr "Autoriser Animath à publier notre vidéo :" #: apps/participation/templates/participation/team_detail.html:42 #: apps/participation/templates/participation/update_team.html:12 #: apps/registration/templates/registration/update_user.html:12 -#: apps/registration/templates/registration/user_detail.html:43 -#: apps/registration/templates/registration/user_detail.html:49 +#: apps/registration/templates/registration/user_detail.html:50 +#: apps/registration/templates/registration/user_detail.html:55 msgid "Update" msgstr "Modifier" @@ -302,92 +302,92 @@ msgstr "rôle" msgid "participant" msgstr "participant" -#: apps/registration/forms.py:14 apps/registration/models.py:132 +#: apps/registration/forms.py:14 apps/registration/models.py:130 msgid "coach" msgstr "encadrant" -#: apps/registration/models.py:22 +#: apps/registration/models.py:20 msgid "Grant Animath to contact me in the future about other actions" msgstr "" "Autoriser Animath à me recontacter à l'avenir à propos d'autres actions" -#: apps/registration/models.py:27 +#: apps/registration/models.py:25 msgid "email confirmed" msgstr "email confirmé" -#: apps/registration/models.py:31 +#: apps/registration/models.py:29 msgid "Activate your Correspondances account" msgstr "Activez votre compte des Correspondances" -#: apps/registration/models.py:67 +#: apps/registration/models.py:65 msgid "registration" msgstr "inscription" -#: apps/registration/models.py:68 +#: apps/registration/models.py:66 msgid "registrations" msgstr "inscriptions" -#: apps/registration/models.py:83 +#: apps/registration/models.py:81 msgid "12th grade" msgstr "Terminale" -#: apps/registration/models.py:84 +#: apps/registration/models.py:82 msgid "11th grade" msgstr "Première" -#: apps/registration/models.py:85 +#: apps/registration/models.py:83 msgid "10th grade or lower" msgstr "Seconde ou inférieur" -#: apps/registration/models.py:87 +#: apps/registration/models.py:85 msgid "student class" msgstr "classe" -#: apps/registration/models.py:92 +#: apps/registration/models.py:90 msgid "school" msgstr "école" -#: apps/registration/models.py:96 +#: apps/registration/models.py:94 msgid "photo authorization" -msgstr "" +msgstr "autorisation de droit à l'image" -#: apps/registration/models.py:104 +#: apps/registration/models.py:102 msgid "student" msgstr "étudiant" -#: apps/registration/models.py:112 +#: apps/registration/models.py:110 msgid "student registration" msgstr "inscription d'élève" -#: apps/registration/models.py:113 +#: apps/registration/models.py:111 msgid "student registrations" msgstr "inscriptions d'élève" -#: apps/registration/models.py:127 +#: apps/registration/models.py:125 msgid "professional activity" msgstr "activité professionnelle" -#: apps/registration/models.py:140 +#: apps/registration/models.py:138 msgid "coach registration" msgstr "inscription d'encadrant" -#: apps/registration/models.py:141 +#: apps/registration/models.py:139 msgid "coach registrations" msgstr "inscriptions d'encadrants" -#: apps/registration/models.py:146 +#: apps/registration/models.py:144 msgid "role of the administrator" msgstr "rôle de l'administrateur" -#: apps/registration/models.py:151 +#: apps/registration/models.py:149 msgid "admin" msgstr "admin" -#: apps/registration/models.py:159 +#: apps/registration/models.py:157 msgid "admin registration" msgstr "inscription d'administrateur" -#: apps/registration/models.py:160 +#: apps/registration/models.py:158 msgid "admin registrations" msgstr "inscriptions d'administrateur" @@ -542,6 +542,11 @@ msgstr "Réinitialiser mon mot de passe" msgid "Sign up" msgstr "Inscription" +#: apps/registration/templates/registration/upload_photo_authorization.html:11 +#: apps/registration/templates/registration/user_detail.html:60 +msgid "Upload" +msgstr "Téléverser" + #: apps/registration/templates/registration/user_detail.html:14 msgid "Last name:" msgstr "Nom de famille :" @@ -571,21 +576,37 @@ msgid "School:" msgstr "École :" #: apps/registration/templates/registration/user_detail.html:31 +msgid "Photo authorization:" +msgstr "Autorisation de droit à l'image" + +#: apps/registration/templates/registration/user_detail.html:34 +msgid "Download" +msgstr "Télécharger" + +#: apps/registration/templates/registration/user_detail.html:35 +msgid "Replace" +msgstr "Remplacer" + +#: apps/registration/templates/registration/user_detail.html:38 msgid "Profesional activity:" msgstr "Activité professionnelle :" -#: apps/registration/templates/registration/user_detail.html:34 +#: apps/registration/templates/registration/user_detail.html:41 msgid "Role:" msgstr "Rôle :" -#: apps/registration/templates/registration/user_detail.html:38 +#: apps/registration/templates/registration/user_detail.html:45 msgid "Grant Animath to contact me in the future about other actions:" msgstr "Autorise Animath à recontacter à propos d'autres actions :" -#: apps/registration/templates/registration/user_detail.html:48 +#: apps/registration/templates/registration/user_detail.html:54 msgid "Update user" msgstr "Modifier l'utilisateur" +#: apps/registration/templates/registration/user_detail.html:59 +msgid "Upload photo authorization" +msgstr "Téléverser l'autorisation de droit à l'image" + #: apps/registration/views.py:56 msgid "Email validation" msgstr "Validation de l'adresse mail"