diff --git a/.gitignore b/.gitignore index 62c8935..b08ff60 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,44 @@ -.idea/ \ No newline at end of file +# Byte-compiled / optimized / DLL files +dist +build +__pycache__ +*.py[cod] +*$py.class +*.swp +*.egg-info +_build +.tox +.coverage +coverage + +# Translations +*.mo +*.pot + +# Jupyter Notebook +.ipynb_checkpoints + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# PyCharm project settings +.idea + +# VSCode project settings +.vscode + +# Local data +secrets.py +*.log +media/ +# Virtualenv +env/ +venv/ +db.sqlite3 + +# Don't git personal data +import_olddb/ diff --git a/.htaccess b/.htaccess deleted file mode 100644 index 73496ca..0000000 --- a/.htaccess +++ /dev/null @@ -1,4 +0,0 @@ -Options +FollowSymlinks -Options -Indexes -RewriteEngine On -RewriteRule ^(.*)$ dispatcher.php?path=$1 [QSA,L] diff --git a/Dockerfile b/Dockerfile index c550e95..ba9dfc8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,39 +1,31 @@ -FROM php:7.3-apache as plateforme-builder +FROM python:3-alpine -# Enabling apache rewrite mod -RUN a2enmod rewrite +ENV PYTHONUNBUFFERED 1 -RUN apt clean && apt update && apt upgrade -y +# Install LaTeX requirements +RUN apk add --no-cache gettext texlive nginx gcc libc-dev libffi-dev postgresql-dev mariadb-connector-c-dev -# Install MySQL drivers -RUN docker-php-ext-install pdo_mysql \ - && docker-php-ext-enable pdo_mysql +RUN apk add --no-cache bash -# Install zip utilities -RUN apt install -y libzip-dev zip \ - && docker-php-ext-configure zip --with-libzip \ - && docker-php-ext-install zip \ - && docker-php-ext-enable zip +RUN mkdir /code +WORKDIR /code +COPY requirements.txt /code/requirements.txt +RUN pip install -r requirements.txt --no-cache-dir -# Setup locales -RUN apt install locales locales-all -y && locale-gen fr_FR.UTF-8 -ENV LANG fr_FR.UTF-8 -ENV LANGUAGE fr_FR:fr -ENV LC_ALL fr_FR.UTF-8 +COPY . /code/ -# Setup timezone -RUN echo Europe/Paris > /etc/timezone \ - && ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime \ - && dpkg-reconfigure -f noninteractive tzdata +# Configure nginx +RUN mkdir /run/nginx +RUN ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log +RUN ln -sf /code/nginx_corres2math.conf /etc/nginx/conf.d/corres2math.conf +RUN rm /etc/nginx/conf.d/default.conf -# Setup mailing -RUN apt install -yq msmtp ca-certificates -COPY setup/msmtprc /etc/msmtprc -RUN echo "sendmail_path=msmtp -t" >> /usr/local/etc/php/conf.d/php-sendmail.ini +RUN cp /code/corres2math.cron /etc/crontabs/corres2math -# Setting environment -ENV CORRES2MATH_LOCAL_PATH /var/www/html -ENV CORRES2MATH_MAIL_DOMAIN correspondances-maths.fr -ENV CORRES2MATH_URL_BASE https://inscription.correspondances-maths.fr +# With a bashrc, the shell is better +RUN ln -s /code/.bashrc /root/.bashrc -RUN chmod 0777 /var/www/html +ENTRYPOINT ["/code/entrypoint.sh"] +EXPOSE 80 + +CMD ["./manage.py", "shell_plus", "--ptpython"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..151f731 --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +# Plateforme d'inscription des Correspondances des Jeunes Mathématicien·nes + +La plateforme des Correspondances des Jeunes Mathématicien·nes est née pour la seconde édition en 2019 de l'action. +D'abord codée en PHP, elle a subi une refonte totale en Python, à l'aide du framework Web [Django](https://www.djangoproject.com/). + +Cette plateforme permet aux participants et encadrants de s'inscrire et de déposer leurs autorisations nécessaires. +Ils pourront ensuite déposer leurs solutions et notes de synthèse pour le premier tour en temps voulu. La plateforme +offre également un accès pour les organisateurs et les jurys leur permettant de communiquer avec les équipes et de +récupérer les documents nécessaires. + +Un wiki plus détaillé arrivera ultérieurement. L'interface organisateur et jury est vouée à être plus poussée. + +L'instance de production est disponible à l'adresse [inscription.correspondances-maths.fr](https://inscription.correspondances-maths.fr). + +## Installation + +Le plus simple pour installer la plateforme est d'utiliser l'image Docker incluse, qui fait tourner un serveur Nginx +exposé sur le port 80 avec le serveur Django. Ci-dessous une configuration Docker-Compose, à adapter selon vos besoins : + +```yaml + inscription-corres2math: + build: ./inscription-corres2math + links: + - postgres + ports: + - "80:80" + env_file: + - ./inscription-corres2math.env + volumes: + # - ./inscription-corres2math:/code + - ./inscription-corres2math/media:/code/media +``` + +Le volume `/code` n'est à ajouter uniquement en développement, et jamais en production. + +Il faut remplir les variables d'environnement suivantes : + +```env +CORRES2MATH_STAGE= # dev ou prod +DJANGO_DB_TYPE= # MySQL, PostgreSQL ou SQLite (par défaut) +DJANGO_DB_HOST= # Hôte de la base de données +DJANGO_DB_NAME= # Nom de la base de données +DJANGO_DB_USER= # Utilisateur de la base de données +DJANGO_DB_PASSWORD= # Mot de passe pour accéder à la base de données +SMTP_HOST= # Hôte SMTP pour l'envoi de mails +SMTP_PORT=465 # Port du serveur SMTP +SMTP_HOST_USER= # Utilisateur du compte SMTP +SMTP_HOST_PASSWORD= # Mot de passe du compte SMTP +FROM_EMAIL=contact@correspondances-maths.fr # Nom de l'expéditeur des mails +SERVER_EMAIL=contact@correspondances-maths.fr # Adresse e-mail expéditrice +``` + +Si le type de base de données sélectionné est SQLite, la variable `DJANGO_DB_HOST` sera utilisée en guise de chemin vers +le fichier de base de données (par défaut, `db.sqlite3`). + +En développement, il est recommandé d'utiliser SQLite pour des raisons de simplicité. Les paramètres de mail ne seront +pas utilisés, et les mails qui doivent être envoyés seront envoyés dans la console. + +En production, il est recommandé de ne pas utiliser SQLite pour des raisons de performances. + +La dernière différence entre le développment et la production est qu'en développement, chaque modification d'un fichier +est détectée et le serveur se relance automatiquement dès lors. + +Une fois le site lancé, le premier compte créé sera un compte administrateur. \ No newline at end of file diff --git a/apps/api/__init__.py b/apps/api/__init__.py new file mode 100644 index 0000000..08884cb --- /dev/null +++ b/apps/api/__init__.py @@ -0,0 +1 @@ +default_app_config = 'api.apps.APIConfig' diff --git a/apps/api/apps.py b/apps/api/apps.py new file mode 100644 index 0000000..6e03468 --- /dev/null +++ b/apps/api/apps.py @@ -0,0 +1,10 @@ +from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ + + +class APIConfig(AppConfig): + """ + Manage the inscription through a JSON API. + """ + name = 'api' + verbose_name = _('API') diff --git a/apps/api/serializers.py b/apps/api/serializers.py new file mode 100644 index 0000000..4e28d20 --- /dev/null +++ b/apps/api/serializers.py @@ -0,0 +1,15 @@ +from django.contrib.auth.models import User +from rest_framework import serializers + +class UserSerializer(serializers.ModelSerializer): + """ + Serialize a User object into JSON. + """ + class Meta: + model = User + exclude = ( + 'username', + 'password', + 'groups', + 'user_permissions', + ) diff --git a/apps/api/urls.py b/apps/api/urls.py new file mode 100644 index 0000000..c2bbfbf --- /dev/null +++ b/apps/api/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls import url, include +from rest_framework import routers + +from .viewsets import UserViewSet + +# Routers provide an easy way of automatically determining the URL conf. +# Register each app API router and user viewset +router = routers.DefaultRouter() +router.register('user', UserViewSet) + +app_name = 'api' + +# Wire up our API using automatic URL routing. +# Additionally, we include login URLs for the browsable API. +urlpatterns = [ + url('^', include(router.urls)), + url('^api-auth/', include('rest_framework.urls', namespace='rest_framework')), +] diff --git a/apps/api/viewsets.py b/apps/api/viewsets.py new file mode 100644 index 0000000..ad6c669 --- /dev/null +++ b/apps/api/viewsets.py @@ -0,0 +1,17 @@ +from django.contrib.auth.models import User +from django_filters.rest_framework import DjangoFilterBackend +from rest_framework.filters import SearchFilter +from rest_framework.viewsets import ModelViewSet + +from .serializers import UserSerializer + + +class UserViewSet(ModelViewSet): + """ + Display list of users. + """ + queryset = User.objects.all() + serializer_class = UserSerializer + filter_backends = [DjangoFilterBackend, SearchFilter] + filterset_fields = ['id', 'first_name', 'last_name', 'email', 'is_superuser', 'is_staff', 'is_active', ] + search_fields = ['$first_name', '$last_name', ] diff --git a/assets/Autorisation de droit à l'image - majeur.pdf b/assets/Autorisation de droit à l'image - majeur.pdf deleted file mode 100644 index b6d8d98..0000000 Binary files a/assets/Autorisation de droit à l'image - majeur.pdf and /dev/null differ diff --git a/assets/Autorisation de droit à l'image - mineur.pdf b/assets/Autorisation de droit à l'image - mineur.pdf deleted file mode 100644 index ea380cb..0000000 Binary files a/assets/Autorisation de droit à l'image - mineur.pdf and /dev/null differ diff --git a/assets/favicon.ico b/assets/favicon.ico deleted file mode 100644 index 8f01ebb..0000000 Binary files a/assets/favicon.ico and /dev/null differ diff --git a/assets/style.css b/assets/style.css deleted file mode 100644 index 5c8d3ff..0000000 --- a/assets/style.css +++ /dev/null @@ -1,47 +0,0 @@ -html, body { - height: 100%; - margin: 0; -} - -:root { - --navbar-height: 32px; -} - -.container { - min-height: 78%; -} - -.inner { - margin: 20px; -} - -.alert { - text-align: justify; -} - - -footer .alert { - text-align: center; -} - -#navbar-logo { - height: var(--navbar-height); - display: block; -} - -ul .deroule { - display: none; - position: absolute; - background: #f8f9fa !important; - list-style-type: none; - padding: 20px; - z-index: 42; -} - -li:hover ul.deroule { - display:block; -} - -a.nav-link:hover { - background-color: #d8d9da; -} diff --git a/corres2math.cron b/corres2math.cron new file mode 100644 index 0000000..113ed0d --- /dev/null +++ b/corres2math.cron @@ -0,0 +1,5 @@ +# m h dom mon dow user command +# Envoyer les mails en attente + * * * * * root cd /code && python manage.py send_mail -c 1 + * * * * * root cd /code && python manage.py retry_deferred -c 1 + 00 0 * * * root cd /code && python manage.py purge_mail_log 7 -c 1 diff --git a/corres2math/__init__.py b/corres2math/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/corres2math/asgi.py b/corres2math/asgi.py new file mode 100644 index 0000000..949b8bb --- /dev/null +++ b/corres2math/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for corres2math project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'corres2math.settings') + +application = get_asgi_application() diff --git a/corres2math/inputs.py b/corres2math/inputs.py new file mode 100644 index 0000000..67838fc --- /dev/null +++ b/corres2math/inputs.py @@ -0,0 +1,322 @@ +from json import dumps as json_dumps + +from django.forms.widgets import DateTimeBaseInput, NumberInput, TextInput, Widget + + +class AmountInput(NumberInput): + """ + This input type lets the user type amounts in euros, but forms receive data in cents + """ + template_name = "amount_input.html" + + def format_value(self, value): + return None if value is None or value == "" else "{:.02f}".format(int(value) / 100, ) + + def value_from_datadict(self, data, files, name): + val = super().value_from_datadict(data, files, name) + return str(int(100 * float(val))) if val else val + + +class Autocomplete(TextInput): + template_name = "autocomplete_model.html" + + def __init__(self, model, attrs=None): + super().__init__(attrs) + + self.model = model + self.model_pk = None + + class Media: + """JS/CSS resources needed to render the date-picker calendar.""" + + js = ('js/autocomplete_model.js', ) + + def format_value(self, value): + if value: + self.attrs["model_pk"] = int(value) + return str(self.model.objects.get(pk=int(value))) + return "" + + +class ColorWidget(Widget): + """ + Pulled from django-colorfield. + Select a color. + """ + template_name = 'colorfield/color.html' + + class Media: + js = [ + 'colorfield/jscolor/jscolor.min.js', + 'colorfield/colorfield.js', + ] + + def format_value(self, value): + if value is None: + value = 0xFFFFFF + return "#{:06X}".format(value) + + def value_from_datadict(self, data, files, name): + val = super().value_from_datadict(data, files, name) + return int(val[1:], 16) + + +""" +The remaining of this file comes from the project `django-bootstrap-datepicker-plus` available on Github: +https://github.com/monim67/django-bootstrap-datepicker-plus +This is distributed under Apache License 2.0. + +This adds datetime pickers with bootstrap. +""" + +"""Contains Base Date-Picker input class for widgets of this package.""" + + +class DatePickerDictionary: + """Keeps track of all date-picker input classes.""" + + _i = 0 + items = dict() + + @classmethod + def generate_id(cls): + """Return a unique ID for each date-picker input class.""" + cls._i += 1 + return 'dp_%s' % cls._i + + +class BasePickerInput(DateTimeBaseInput): + """Base Date-Picker input class for widgets of this package.""" + + template_name = 'bootstrap_datepicker_plus/date_picker.html' + picker_type = 'DATE' + format = '%Y-%m-%d' + config = {} + _default_config = { + 'id': None, + 'picker_type': None, + 'linked_to': None, + 'options': {} # final merged options + } + options = {} # options extended by user + options_param = {} # options passed as parameter + _default_options = { + 'showClose': True, + 'showClear': True, + 'showTodayButton': True, + "locale": "fr", + } + + # source: https://github.com/tutorcruncher/django-bootstrap3-datetimepicker + # file: /blob/31fbb09/bootstrap3_datetime/widgets.py#L33 + format_map = ( + ('DDD', r'%j'), + ('DD', r'%d'), + ('MMMM', r'%B'), + ('MMM', r'%b'), + ('MM', r'%m'), + ('YYYY', r'%Y'), + ('YY', r'%y'), + ('HH', r'%H'), + ('hh', r'%I'), + ('mm', r'%M'), + ('ss', r'%S'), + ('a', r'%p'), + ('ZZ', r'%z'), + ) + + class Media: + """JS/CSS resources needed to render the date-picker calendar.""" + + js = ( + 'https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.9.0/' + 'moment-with-locales.min.js', + 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/' + '4.17.47/js/bootstrap-datetimepicker.min.js', + 'bootstrap_datepicker_plus/js/datepicker-widget.js' + ) + css = {'all': ( + 'https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/' + '4.17.47/css/bootstrap-datetimepicker.css', + 'bootstrap_datepicker_plus/css/datepicker-widget.css' + ), } + + @classmethod + def format_py2js(cls, datetime_format): + """Convert python datetime format to moment datetime format.""" + for js_format, py_format in cls.format_map: + datetime_format = datetime_format.replace(py_format, js_format) + return datetime_format + + @classmethod + def format_js2py(cls, datetime_format): + """Convert moment datetime format to python datetime format.""" + for js_format, py_format in cls.format_map: + datetime_format = datetime_format.replace(js_format, py_format) + return datetime_format + + def __init__(self, attrs=None, format=None, options=None): + """Initialize the Date-picker widget.""" + self.format_param = format + self.options_param = options if options else {} + self.config = self._default_config.copy() + self.config['id'] = DatePickerDictionary.generate_id() + self.config['picker_type'] = self.picker_type + self.config['options'] = self._calculate_options() + attrs = attrs if attrs else {} + if 'class' not in attrs: + attrs['class'] = 'form-control' + super().__init__(attrs, self._calculate_format()) + + def _calculate_options(self): + """Calculate and Return the options.""" + _options = self._default_options.copy() + _options.update(self.options) + if self.options_param: + _options.update(self.options_param) + return _options + + def _calculate_format(self): + """Calculate and Return the datetime format.""" + _format = self.format_param if self.format_param else self.format + if self.config['options'].get('format'): + _format = self.format_js2py(self.config['options'].get('format')) + else: + self.config['options']['format'] = self.format_py2js(_format) + return _format + + def get_context(self, name, value, attrs): + """Return widget context dictionary.""" + context = super().get_context( + name, value, attrs) + context['widget']['attrs']['dp_config'] = json_dumps(self.config) + return context + + def start_of(self, event_id): + """ + Set Date-Picker as the start-date of a date-range. + + Args: + - event_id (string): User-defined unique id for linking two fields + """ + DatePickerDictionary.items[str(event_id)] = self + return self + + def end_of(self, event_id, import_options=True): + """ + Set Date-Picker as the end-date of a date-range. + + Args: + - event_id (string): User-defined unique id for linking two fields + - import_options (bool): inherit options from start-date input, + default: TRUE + """ + event_id = str(event_id) + if event_id in DatePickerDictionary.items: + linked_picker = DatePickerDictionary.items[event_id] + self.config['linked_to'] = linked_picker.config['id'] + if import_options: + backup_moment_format = self.config['options']['format'] + self.config['options'].update(linked_picker.config['options']) + self.config['options'].update(self.options_param) + if self.format_param or 'format' in self.options_param: + self.config['options']['format'] = backup_moment_format + else: + self.format = linked_picker.format + # Setting useCurrent is necessary, see following issue + # https://github.com/Eonasdan/bootstrap-datetimepicker/issues/1075 + self.config['options']['useCurrent'] = False + self._link_to(linked_picker) + else: + raise KeyError( + 'start-date not specified for event_id "%s"' % event_id) + return self + + def _link_to(self, linked_picker): + """ + Executed when two date-inputs are linked together. + + This method for sub-classes to override to customize the linking. + """ + pass + + +class DatePickerInput(BasePickerInput): + """ + Widget to display a Date-Picker Calendar on a DateField property. + + Args: + - attrs (dict): HTML attributes of rendered HTML input + - format (string): Python DateTime format eg. "%Y-%m-%d" + - options (dict): Options to customize the widget, see README + """ + + picker_type = 'DATE' + format = '%Y-%m-%d' + format_key = 'DATE_INPUT_FORMATS' + + +class TimePickerInput(BasePickerInput): + """ + Widget to display a Time-Picker Calendar on a TimeField property. + + Args: + - attrs (dict): HTML attributes of rendered HTML input + - format (string): Python DateTime format eg. "%Y-%m-%d" + - options (dict): Options to customize the widget, see README + """ + + picker_type = 'TIME' + format = '%H:%M' + format_key = 'TIME_INPUT_FORMATS' + template_name = 'bootstrap_datepicker_plus/time_picker.html' + + +class DateTimePickerInput(BasePickerInput): + """ + Widget to display a DateTime-Picker Calendar on a DateTimeField property. + + Args: + - attrs (dict): HTML attributes of rendered HTML input + - format (string): Python DateTime format eg. "%Y-%m-%d" + - options (dict): Options to customize the widget, see README + """ + + picker_type = 'DATETIME' + format = '%Y-%m-%d %H:%M' + format_key = 'DATETIME_INPUT_FORMATS' + + +class MonthPickerInput(BasePickerInput): + """ + Widget to display a Month-Picker Calendar on a DateField property. + + Args: + - attrs (dict): HTML attributes of rendered HTML input + - format (string): Python DateTime format eg. "%Y-%m-%d" + - options (dict): Options to customize the widget, see README + """ + + picker_type = 'MONTH' + format = '01/%m/%Y' + format_key = 'DATE_INPUT_FORMATS' + + +class YearPickerInput(BasePickerInput): + """ + Widget to display a Year-Picker Calendar on a DateField property. + + Args: + - attrs (dict): HTML attributes of rendered HTML input + - format (string): Python DateTime format eg. "%Y-%m-%d" + - options (dict): Options to customize the widget, see README + """ + + picker_type = 'YEAR' + format = '01/01/%Y' + format_key = 'DATE_INPUT_FORMATS' + + def _link_to(self, linked_picker): + """Customize the options when linked with other date-time input""" + yformat = self.config['options']['format'].replace('-01-01', '-12-31') + self.config['options']['format'] = yformat diff --git a/corres2math/middlewares.py b/corres2math/middlewares.py new file mode 100644 index 0000000..fa1b83b --- /dev/null +++ b/corres2math/middlewares.py @@ -0,0 +1,93 @@ +from django.conf import settings +from django.contrib.auth.models import AnonymousUser, User + +from threading import local + +from django.contrib.sessions.backends.db import SessionStore + +USER_ATTR_NAME = getattr(settings, 'LOCAL_USER_ATTR_NAME', '_current_user') +SESSION_ATTR_NAME = getattr(settings, 'LOCAL_SESSION_ATTR_NAME', '_current_session') +IP_ATTR_NAME = getattr(settings, 'LOCAL_IP_ATTR_NAME', '_current_ip') + +_thread_locals = local() + + +def _set_current_user_and_ip(user=None, session=None, ip=None): + setattr(_thread_locals, USER_ATTR_NAME, user) + setattr(_thread_locals, SESSION_ATTR_NAME, session) + setattr(_thread_locals, IP_ATTR_NAME, ip) + + +def get_current_user() -> User: + return getattr(_thread_locals, USER_ATTR_NAME, None) + + +def get_current_session() -> SessionStore: + return getattr(_thread_locals, SESSION_ATTR_NAME, None) + + +def get_current_ip() -> str: + return getattr(_thread_locals, IP_ATTR_NAME, None) + + +def get_current_authenticated_user(): + current_user = get_current_user() + if isinstance(current_user, AnonymousUser): + return None + return current_user + + +class SessionMiddleware(object): + """ + This middleware get the current user with his or her IP address on each request. + """ + + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + if "_fake_user_id" in request.session: + request.user = User.objects.get(pk=request.session["_fake_user_id"]) + + user = request.user + if 'HTTP_X_FORWARDED_FOR' in request.META: + ip = request.META.get('HTTP_X_FORWARDED_FOR') + else: + ip = request.META.get('REMOTE_ADDR') + + _set_current_user_and_ip(user, request.session, ip) + response = self.get_response(request) + _set_current_user_and_ip(None, None, None) + + return response + + +class TurbolinksMiddleware(object): + """ + Send the `Turbolinks-Location` header in response to a visit that was redirected, + and Turbolinks will replace the browser's topmost history entry. + """ + + def __init__(self, get_response): + self.get_response = get_response + + def __call__(self, request): + response = self.get_response(request) + + is_turbolinks = request.META.get('HTTP_TURBOLINKS_REFERRER') + is_response_redirect = response.has_header('Location') + + if is_turbolinks: + if is_response_redirect: + location = response['Location'] + prev_location = request.session.pop('_turbolinks_redirect_to', None) + if prev_location is not None: + # relative subsequent redirect + if location.startswith('.'): + location = prev_location.split('?')[0] + location + request.session['_turbolinks_redirect_to'] = location + else: + if request.session.get('_turbolinks_redirect_to'): + location = request.session.pop('_turbolinks_redirect_to') + response['Turbolinks-Location'] = location + return response diff --git a/corres2math/settings.py b/corres2math/settings.py new file mode 100644 index 0000000..fcfe553 --- /dev/null +++ b/corres2math/settings.py @@ -0,0 +1,202 @@ +""" +Django settings for corres2math project. + +Generated by 'django-admin startproject' using Django 3.0.5. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.0/ref/settings/ +""" + +import os +import sys + +from django.utils.translation import gettext_lazy as _ + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +APPS_DIR = os.path.realpath(os.path.join(BASE_DIR, "apps")) +sys.path.append(APPS_DIR) + +ADMINS = [("Yohann D'ANELLO", "yohann.danello@animath.fr")] + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '6$wl1=ehfoiymin3m3i-wyx5d3t=1h7g4(j2izn*my)*yiq#he' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +SITE_ID = 1 + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.sites', + 'django.contrib.messages', + 'django.contrib.staticfiles', + 'django.forms', + + 'bootstrap_datepicker_plus', + 'crispy_forms', + 'django_extensions', + 'django_tables2', + 'mailer', + 'polymorphic', + 'rest_framework', + 'rest_framework.authtoken', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.contrib.sites.middleware.CurrentSiteMiddleware', + 'corres2math.middlewares.SessionMiddleware', + 'corres2math.middlewares.TurbolinksMiddleware', +] + +ROOT_URLCONF = 'corres2math.urls' + +LOGIN_REDIRECT_URL = "index" + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')] + , + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' + +WSGI_APPLICATION = 'corres2math.wsgi.application' + + +# Password validation +# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + +PASSWORD_HASHERS = [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', + 'django.contrib.auth.hashers.BCryptPasswordHasher', +] + +REST_FRAMEWORK = { + 'DEFAULT_PERMISSION_CLASSES': [ + 'rest_framework.permissions.IsAdminUser' + ], + 'DEFAULT_AUTHENTICATION_CLASSES': [ + 'rest_framework.authentication.SessionAuthentication', + 'rest_framework.authentication.TokenAuthentication', + ], + 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', + 'PAGE_SIZE': 50, +} + +# Internationalization +# https://docs.djangoproject.com/en/3.0/topics/i18n/ + +LANGUAGE_CODE = 'en' + +LANGUAGES = [ + ('en', _('English')), + ('fr', _('French')), +] + +TIME_ZONE = 'Europe/Paris' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")] + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.0/howto/static-files/ + +STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "corres2math/static"), +] + +STATIC_ROOT = os.path.join(BASE_DIR, "static") + +MEDIA_URL = '/media/' + +MEDIA_ROOT = os.path.join(BASE_DIR, "media") + +CRISPY_TEMPLATE_PACK = 'bootstrap4' + +DJANGO_TABLES2_TEMPLATE = 'django_tables2/bootstrap4.html' + +_db_type = os.getenv('DJANGO_DB_TYPE', 'sqlite').lower() + +if _db_type == 'mysql' or _db_type.startswith('postgres') or _db_type == 'psql': + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.mysql' if _db_type == 'mysql' else 'django.db.backends.postgresql_psycopg2', + 'NAME': os.environ.get('DJANGO_DB_NAME', 'corres2math'), + 'USER': os.environ.get('DJANGO_DB_USER', 'corres2math'), + 'PASSWORD': os.environ.get('DJANGO_DB_PASSWORD', 'CHANGE_ME_IN_ENV_SETTINGS'), + 'HOST': os.environ.get('DJANGO_DB_HOST', 'localhost'), + 'PORT': os.environ.get('DJANGO_DB_PORT', ''), # Use default port + } + } +else: + DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, os.getenv('DJANGO_DB_HOST', 'db.sqlite3')), + } + } + +if os.getenv("CORRES2MATH_STAGE", "dev") == "prod": + from .settings_prod import * +else: + from .settings_dev import * diff --git a/corres2math/settings_dev.py b/corres2math/settings_dev.py new file mode 100644 index 0000000..a52990e --- /dev/null +++ b/corres2math/settings_dev.py @@ -0,0 +1,5 @@ +# Database +# https://docs.djangoproject.com/en/3.0/ref/settings/#databases + +EMAIL_BACKEND = 'mailer.backend.DbBackend' +MAILER_EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' diff --git a/corres2math/settings_prod.py b/corres2math/settings_prod.py new file mode 100644 index 0000000..539eb41 --- /dev/null +++ b/corres2math/settings_prod.py @@ -0,0 +1,30 @@ +import os + +# Break it, fix it! +DEBUG = False + +# Mandatory ! +ALLOWED_HOSTS = ['inscription.correspondances-maths.fr', 'plateforme.correspondances-maths.fr'] + +SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'CHANGE_ME_IN_ENV_SETTINGS') + +# Emails +EMAIL_BACKEND = 'mailer.backend.DbBackend' +MAILER_EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' +EMAIL_USE_SSL = True +EMAIL_HOST = os.getenv("SMTP_HOST") +EMAIL_PORT = os.getenv("SMTP_PORT") +EMAIL_HOST_USER = os.getenv("SMTP_HOST_USER") +EMAIL_HOST_PASSWORD = os.getenv("SMTP_HOST_PASSWORD") + +DEFAULT_FROM_EMAIL = os.getenv('FROM_EMAIL', 'Contact Correspondances ') +SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'contact@correspondances-maths.fr') + +# Security settings +SECURE_CONTENT_TYPE_NOSNIFF = False +SECURE_BROWSER_XSS_FILTER = False +SESSION_COOKIE_SECURE = False +CSRF_COOKIE_SECURE = False +CSRF_COOKIE_HTTPONLY = False +X_FRAME_OPTIONS = 'DENY' +SESSION_COOKIE_AGE = 60 * 60 * 3 diff --git a/corres2math/static/favicon.ico b/corres2math/static/favicon.ico new file mode 100644 index 0000000..69e1a32 Binary files /dev/null and b/corres2math/static/favicon.ico differ diff --git a/assets/logo.png b/corres2math/static/logo.png similarity index 100% rename from assets/logo.png rename to corres2math/static/logo.png diff --git a/corres2math/urls.py b/corres2math/urls.py new file mode 100644 index 0000000..ab9e636 --- /dev/null +++ b/corres2math/urls.py @@ -0,0 +1,35 @@ +"""corres2math URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +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.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 + +urlpatterns = [ + path('', TemplateView.as_view(template_name="index.html"), name='index'), + path('i18n/', include('django.conf.urls.i18n')), + path('admin/doc/', include('django.contrib.admindocs.urls')), + path('admin/', admin.site.urls, name="admin"), + path('accounts/', include('django.contrib.auth.urls')), + + path('api/', include('api.urls')), +] + +handler400 = bad_request +handler403 = permission_denied +handler404 = page_not_found +handler500 = server_error diff --git a/corres2math/wsgi.py b/corres2math/wsgi.py new file mode 100644 index 0000000..0cae477 --- /dev/null +++ b/corres2math/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for corres2math project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'corres2math.settings') + +application = get_wsgi_application() diff --git a/dispatcher.php b/dispatcher.php deleted file mode 100644 index b6cf0f3..0000000 --- a/dispatcher.php +++ /dev/null @@ -1,95 +0,0 @@ - $file) { - if (preg_match('#' . $route . '#', $path, $matches)) { - for ($i = 1; $i < sizeof($file); ++$i) - $_GET[$file[$i]] = $matches[$i]; - - if (!preg_match("#php$#", $file[0])) { - header("Content-Type: " . $file[1]); - readfile($file[0]); - exit(); - } - - /** @noinspection PhpIncludeInspection */ - require $file[0]; - exit(); - } -} - -require_once "server_files/404.php"; diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..0029acc --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +python manage.py compilemessages +python manage.py migrate + +nginx + +if [ "$CORRES2MATH_STAGE" = "prod" ]; then + gunicorn -b 0.0.0.0:8000 --workers=2 --threads=4 --worker-class=gthread corres2math.wsgi --access-logfile '-' --error-logfile '-'; +else + ./manage.py runserver 0.0.0.0:8000; +fi diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..4b42e94 --- /dev/null +++ b/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,270 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: Corres2math\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-09-20 22:31+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Yohann D'ANELLO \n" +"Language-Team: LANGUAGE \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: apps/api/apps.py:10 +msgid "API" +msgstr "API" + +#: corres2math/settings.py:144 +msgid "English" +msgstr "Anglais" + +#: corres2math/settings.py:145 +msgid "French" +msgstr "Français" + +#: templates/400.html:6 +msgid "Bad request" +msgstr "Requête invalide" + +#: templates/400.html:7 +msgid "" +"Sorry, your request was bad. Don't know what could be wrong. An email has " +"been sent to webmasters with the details of the error. You can now watch " +"some videos." +msgstr "" +"Désolé, votre requête est invalide. Aucune idée de ce qui a pu se passer. Un " +"email a été envoyé aux administrateurs avec les détails de l'erreur. Vous " +"pouvez désormais retourner voir des vidéos." + +#: templates/403.html:6 +msgid "Permission denied" +msgstr "Permission refusée" + +#: templates/403.html:7 +msgid "You don't have the right to perform this request." +msgstr "Vous n'avez pas le droit d'effectuer cette requête." + +#: templates/403.html:10 templates/404.html:10 +msgid "Exception message:" +msgstr "Message d'erreur :" + +#: templates/404.html:6 +msgid "Page not found" +msgstr "Page non trouvée" + +#: templates/404.html:7 +#, python-format +msgid "" +"The requested path %(request_path)s was not found on the server." +msgstr "" +"Le chemin demandé %(request_path)s n'a pas été trouvé sur le " +"serveur." + +#: templates/500.html:6 +msgid "Server error" +msgstr "Erreur du serveur" + +#: templates/500.html:7 +msgid "" +"Sorry, an error occurred when processing your request. An email has been " +"sent to webmasters with the detail of the error, and this will be fixed " +"soon. You can now watch some videos." +msgstr "" +"Désolé, une erreur est survenue lors du traitement de votre requête. Aucune " +"idée de ce qui a pu se passer. Un email a été envoyé aux administrateurs " +"avec les détails de l'erreur. Vous pouvez désormais retourner voir des " +"vidéos." + +#: templates/base.html:70 +msgid "Home" +msgstr "Accueil" + +#: templates/base.html:74 +msgid "Make a gift" +msgstr "Faire un don" + +#: templates/base.html:78 +msgid "Administration" +msgstr "Administration" + +#: templates/base.html:85 +msgid "Return to admin view" +msgstr "Retourner à l'interface administrateur" + +#: templates/base.html:90 templates/registration/login.html:7 +#: templates/registration/login.html:8 templates/registration/login.html:22 +#: templates/registration/password_reset_complete.html:10 +msgid "Log in" +msgstr "Connexion" + +#: templates/base.html:94 +msgid "Log out" +msgstr "Déconnexion" + +#: templates/base.html:118 +msgid "Contact us" +msgstr "Nous contacter" + +#: templates/base.html:141 +msgid "Back to top" +msgstr "Retour en haut" + +#: templates/registration/email_validation_complete.html:15 +msgid "Your email have successfully been validated." +msgstr "Votre email a été validé avec succès." + +#: templates/registration/email_validation_complete.html:18 +#, python-format +msgid "You can now log in." +msgstr "Vous pouvez désormais vous connecter." + +#: templates/registration/email_validation_complete.html:22 +msgid "" +"The link was invalid. The token may have expired. Please send us an email to " +"activate your account." +msgstr "" +"Le lien est invalide. Le jeton a peut-être expiré. Merci de nous envoyer un " +"mail pour activer votre compte." + +#: templates/registration/email_validation_email_sent.html:10 +msgid "Account activation" +msgstr "Activation du compte" + +#: templates/registration/email_validation_email_sent.html:14 +msgid "" +"An email has been sent. Please click on the link to activate your account." +msgstr "" +"Un email a été envoyé. Merci de cliquer sur le lien pour activer votre " +"compte." + +#: templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Merci d'avoir utilisé la plateforme des Correspondances." + +#: templates/registration/logged_out.html:9 +msgid "Log in again" +msgstr "Se reconnecter" + +#: templates/registration/login.html:13 +#, python-format +msgid "" +"You are authenticated as %(user)s, but are not authorized to access this " +"page. Would you like to login to a different account?" +msgstr "" +"Vous êtes connectés en tant que %(user)s, mais n'êtes pas autorisés à " +"accéder à cette page. Voulez-vous vous reconnecter avec un autre compte ?" + +#: templates/registration/login.html:23 +msgid "Forgotten your password or username?" +msgstr "Mot de passe oublié ?" + +#: templates/registration/mails/email_validation_email.html:12 +#: templates/registration/mails/email_validation_email.txt:3 +msgid "Hi" +msgstr "Bonjour" + +#: templates/registration/mails/email_validation_email.html:16 +#: templates/registration/mails/email_validation_email.txt:5 +msgid "" +"You recently registered on the Correspondances platform. Please click on the " +"link below to confirm your registration." +msgstr "" + +#: templates/registration/mails/email_validation_email.html:26 +#: templates/registration/mails/email_validation_email.txt:9 +msgid "" +"This link is only valid for a couple of days, after that you will need to " +"contact us to validate your email." +msgstr "" + +#: templates/registration/mails/email_validation_email.html:30 +#: templates/registration/mails/email_validation_email.txt:11 +msgid "Thanks" +msgstr "Merci" + +#: templates/registration/mails/email_validation_email.html:35 +#: templates/registration/mails/email_validation_email.txt:13 +msgid "The CNO." +msgstr "" + +#: templates/registration/password_change_done.html:8 +msgid "Your password was changed." +msgstr "Votre mot de passe a été changé." + +#: templates/registration/password_change_form.html:9 +msgid "" +"Please enter your old password, for security's sake, and then enter your new " +"password twice so we can verify you typed it in correctly." +msgstr "" +"Merci d'entrer votre ancien mot de passe pour des raisons de sécurité, et " +"d'entrer votre nouveau mot de passe deux fois afin de s'assurer que vous " +"l'ayez tapé correctement." + +#: templates/registration/password_change_form.html:11 +#: templates/registration/password_reset_confirm.html:12 +msgid "Change my password" +msgstr "Changer mon mot de passe" + +#: templates/registration/password_reset_complete.html:8 +msgid "Your password has been set. You may go ahead and log in now." +msgstr "Votre mot de passe a été changé. Vous pouvez désormais vous connecter." + +#: templates/registration/password_reset_confirm.html:9 +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" +"Merci d'entrer votre nouveau mot de passe deux fois afin de vérifier que " +"vous l'ayez tapé correctement." + +#: templates/registration/password_reset_confirm.html:15 +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" +"Le lien de réinitialisation du mot de passe est invalide, probablement parce " +"qu'il a déjà été utilisé. Merci de demander une nouvelle réinitialisation du " +"mot de passe." + +#: templates/registration/password_reset_done.html:8 +msgid "" +"We've emailed you instructions for setting your password, if an account " +"exists with the email you entered. You should receive them shortly." +msgstr "" +"Nous vous avons envoyé un email contenant des instructions pour définir " +"votre mot de passe, si un compte existe avec l'adresse mail que vous avez " +"entrée. Vous devriez le recevoir très rapidement." + +#: templates/registration/password_reset_done.html:9 +msgid "" +"If you don't receive an email, please make sure you've entered the address " +"you registered with, and check your spam folder." +msgstr "" +"Si vous ne recevez pas de mail, merci de vous assurer que vous avez entré " +"l'adresse mail avec laquelle vous êtes inscrits, et de vérifier vos " +"courriers indésirables." + +#: templates/registration/password_reset_form.html:8 +msgid "" +"Forgotten your password? Enter your email address below, and we'll email " +"instructions for setting a new one." +msgstr "" +"Mot de passe oublié ? Entrez votre adresse mail ci-dessous, et nous vous " +"enverrons un mail avec les instructions pour en définir un nouveau." + +#: templates/registration/password_reset_form.html:11 +msgid "Reset my password" +msgstr "Réinitialiser mon mot de passe" + +#: templates/registration/signup.html:5 templates/registration/signup.html:8 +#: templates/registration/signup.html:14 +msgid "Sign up" +msgstr "Inscription" diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..c481888 --- /dev/null +++ b/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'corres2math.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/nginx_corres2math.conf b/nginx_corres2math.conf new file mode 100644 index 0000000..e4b01f0 --- /dev/null +++ b/nginx_corres2math.conf @@ -0,0 +1,19 @@ +upstream corres2math { + server 127.0.0.1:8000; +} + +server { + listen 80; + server_name corres2math; + + location / { + proxy_pass http://corres2math; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $host; + proxy_redirect off; + } + + location /static { + alias /code/static/; + } +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c3358c4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,15 @@ +bcrypt +Django~=3.0 +django-allauth +django-bootstrap-datepicker-plus +django-crispy-forms +django-extensions +django-filter +django-mailer +django-polymorphic +django-tables2 +djangorestframework +django-rest-polymorphic +psycopg2-binary +ptpython +gunicorn \ No newline at end of file diff --git a/server_files/403.php b/server_files/403.php deleted file mode 100644 index 72127d0..0000000 --- a/server_files/403.php +++ /dev/null @@ -1,16 +0,0 @@ - - -
-

- Vous n'êtes pas autorisé à accéder à cette page. -

-
- - - -
-

- Cette page n'existe pas. -

-
- -prepare("SELECT * FROM `documents` WHERE `file_id` = ?;"); - $req->execute([htmlspecialchars($id)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - return self::fromData($data); - } - - public static function fromData($data) - { - $doc = new Document(); - $doc->fill($data); - return $doc; - } - - private function fill($data) - { - $this->file_id = $data["file_id"]; - $this->user_id = $data["user"]; - $this->team_id = $data["team"]; - $this->problem = $data["problem"]; - $this->uploaded_at = $data["uploaded_at"]; - $this->version = isset($data["version"]) ? $data["version"] : 1; - } - - public function getFileId() - { - return $this->file_id; - } - - public function getUserId() - { - return $this->user_id; - } - - public function getTeamId() - { - return $this->team_id; - } - - public function getProblem() - { - return $this->problem; - } - - public function getUploadedAt() - { - return $this->uploaded_at; - } - - public function getVersion() - { - return $this->version; - } - - - - public static function getAllDocuments($problem, $team_id = -1) - { - global $DB; - $req = $DB->query("SELECT * FROM `documents` AS `t1` " - . "INNER JOIN (SELECT `user`, `problem`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `problem`, `user`) `t2` " - . "ON `t1`.`user` = `t2`.`user` AND `t1`.`problem` = `t2`.`problem` " - . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`problem` = $problem " . ($team_id >= 0 ? "AND `team` = $team_id" : "") . " ORDER BY `t1`.`user`;"); - - $docs = []; - - while (($data = $req->fetch()) !== false) - $docs[] = Document::fromData($data); - - return $docs; - } -} diff --git a/server_files/classes/Phase.php b/server_files/classes/Phase.php deleted file mode 100644 index 7cb6669..0000000 --- a/server_files/classes/Phase.php +++ /dev/null @@ -1,68 +0,0 @@ -getStartPhase1Date()) - return self::INSCRIPTION; - - if ($date < $CONFIG->getEndPhase1Date()) - return self::PHASE1; - - if ($date < $CONFIG->getStartPhase2Date()) - return self::PHASE12; - - if ($date < $CONFIG->getEndPhase2Date()) - return self::PHASE2; - - if ($date < $CONFIG->getStartPhase3Date()) - return self::PHASE23; - - if ($date < $CONFIG->getEndPhase3Date()) - return self::PHASE3; - - if ($date < $CONFIG->getStartPhase4Date()) - return self::PHASE34; - - if ($date < $CONFIG->getEndPhase4Date()) - return self::PHASE4; - - return self::END; - } - - public static function getTranslatedName($phase) - { - switch ($phase) - { - case self::INSCRIPTION: - return "Inscription"; - case self::PHASE1: - return "Phase 1 (soumission des vidéos)"; - case self::PHASE2: - return "Phase 2 (questions)"; - case self::PHASE3: - return "Phase 3 (réponses)"; - case self::PHASE4: - return "Phase 4 (vidéo de réponse)"; - case self::END: - return "Les Correspondances sont terminées"; - default: - return "Entre deux phases"; - } - } -} \ No newline at end of file diff --git a/server_files/classes/Question.php b/server_files/classes/Question.php deleted file mode 100644 index f31fe3c..0000000 --- a/server_files/classes/Question.php +++ /dev/null @@ -1,185 +0,0 @@ -prepare("SELECT * FROM `questions` WHERE `id` = ?;"); - $req->execute(htmlspecialchars($id)); - $data = $req->fetch(); - - if ($data === false) - return null; - - $question = new Question(); - $question->fill($data); - return $question; - } - - public static function fromAttachedFile($attached_file) - { - global $DB; - - $req = $DB->prepare("SELECT * FROM `questions` WHERE `attached_file` = ? OR `attached_file_answer` = ?;"); - $req->execute([htmlspecialchars($attached_file), htmlspecialchars($attached_file)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $question = new Question(); - $question->fill($data); - return $question; - } - - public function fill($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - } - - public static function getQuestions(Team $from, Team $to) - { - global $DB; - - ensure($from->getProblem() == $to->getProblem(), "Les deux équipes doivent travailler sur le même problème."); - - $req = $DB->prepare("SELECT * FROM `questions` WHERE `from` = ? AND `to` = ? ORDER BY `from`, `number`;"); - $req->execute([$from->getId(), $to->getId()]); - - $questions = []; - - while (($data = $req->fetch()) !== false) { - $question = new Question(); - $question->fill($data); - $questions[] = $question; - } - - if (sizeof($questions) == 0) { - $req = $DB->prepare("INSERT INTO `questions`(`from`, `to`, `problem`, `number`, `question`) VALUES (?, ?, ?, ?, ?);"); - $req->execute([$from->getId(), $to->getId(), $from->getProblem(), 0, ""]); - for ($i = 1; $i <= 6; ++$i) { - $req = $DB->prepare("INSERT INTO `questions`(`from`, `to`, `problem`, `number`, `question`) VALUES (?, ?, ?, ?, ?);"); - $req->execute([$from->getId(), $to->getId(), $from->getProblem(), $i, self::DEFAULT_QUESTIONS[$i - 1]]); - } - return self::getQuestions($from, $to); - } - - return $questions; - } - - public static function getQuestionsTo(Team $to) - { - global $DB, $YEAR; - $id = $to->getId(); - $req = $DB->query("SELECT `id` from `teams` WHERE (`video_team1` = $id OR `video_team2` = $id) AND `year` = $YEAR;"); - - $questions = []; - - while (($data = $req->fetch()) !== false) - $questions[] = self::getQuestions(Team::fromId($data["id"]), $to); - - return $questions; - } - - public function getId() - { - return $this->id; - } - - public function getFrom() - { - return $this->from; - } - - public function getTo() - { - return $this->to; - } - - public function getProblem() - { - return $this->problem; - } - - public function getNumber() - { - return $this->number; - } - - public function getQuestion() - { - return $this->question; - } - - public function setQuestion($question) - { - global $DB; - $this->question = $question; - $req = $DB->prepare("UPDATE `questions` SET `question` = ? WHERE `id` = ?;"); - $req->execute([$question, $this->id]); - } - - public function getAttachedFile() - { - return $this->attached_file; - } - - public function setAttachedFile($attached_file) - { - global $DB; - $this->attached_file = $attached_file; - $req = $DB->prepare("UPDATE `questions` SET `attached_file` = ? WHERE `id` = ?;"); - $req->execute([$attached_file, $this->id]); - } - - public function getAnswer() - { - return $this->answer; - } - - public function setAnswer($answer) - { - global $DB; - $this->answer = $answer; - $req = $DB->prepare("UPDATE `questions` SET `answer` = ? WHERE `id` = ?;"); - $req->execute([$answer, $this->id]); - } - - public function getAttachedFileAnswer() - { - return $this->attached_file_answer; - } - - public function setAttachedFileAnswer($attached_file) - { - global $DB; - $this->attached_file_answer = $attached_file; - $req = $DB->prepare("UPDATE `questions` SET `attached_file_answer` = ? WHERE `id` = ?;"); - $req->execute([$attached_file, $this->id]); - } -} \ No newline at end of file diff --git a/server_files/classes/Reason.php b/server_files/classes/Reason.php deleted file mode 100644 index dece59f..0000000 --- a/server_files/classes/Reason.php +++ /dev/null @@ -1,41 +0,0 @@ -prepare("SELECT * FROM `teams` WHERE `id` = ?;"); - $req->execute([htmlspecialchars($id)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $team = new Team(); - $team->fill($data); - return $team; - } - - /** - * @param $trigram - * @return Team|null - */ - public static function fromTrigram($trigram) - { - global $DB, $YEAR; - $req = $DB->prepare("SELECT * FROM `teams` WHERE `trigram` = ? AND `year` = $YEAR;"); - $req->execute([htmlspecialchars($trigram)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $team = new Team(); - $team->fill($data); - return $team; - } - - public static function fromAccessCode($access_code) - { - global $DB, $YEAR; - $req = $DB->prepare("SELECT * FROM `teams` WHERE `access_code` = ? AND `year` = $YEAR;"); - $req->execute([htmlspecialchars($access_code)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $team = new Team(); - $team->fill($data); - return $team; - } - - public static function getAllTeams($problem = -1, $only_validated = false, $only_with_solutions = true) - { - global $DB, $YEAR; - $req = $DB->prepare("SELECT * FROM `teams` WHERE " . ($problem < 0 ? "" : "`problem` = ? AND ") . ($only_validated ? "`validation_status` = 'VALIDATED' AND " : "") . "`year` = $YEAR;"); - $req->execute([htmlspecialchars($problem)]); - - $teams = []; - - while (($data = $req->fetch()) != false) { - $team = new Team(); - $team->fill($data); - $sol = $team->getSolution(); - if ($sol != null && $sol->getValidation() == ValidationStatus::VALIDATED - 1) - $teams[] = $team; - } - - return $teams; - } - - private function fill($data) - { - $this->id = $data["id"]; - $this->name = $data["name"]; - $this->trigram = $data["trigram"]; - $this->problem = $data["problem"]; - $this->encadrant = $data["encadrant"]; - $this->participants = [$data["participant_1"], $data["participant_2"], $data["participant_3"], $data["participant_4"], $data["participant_5"]]; - $this->inscription_date = $data["inscription_date"]; - $this->allow_publish = $data["allow_publish"] ? 1 : 0; - $this->validation_status = ValidationStatus::fromName($data["validation_status"]); - $this->video_team_ids = [$data["video_team1"], $data["video_team2"]]; - $this->access_code = $data["access_code"]; - $this->year = $data["year"]; - } - - public function getId() - { - return $this->id; - } - - public function getName() - { - return $this->name; - } - - public function setName($name) - { - global $DB; - $this->name = $name; - $DB->prepare("UPDATE `teams` SET `name` = ? WHERE `id` = ?;")->execute([$name, $this->id]); - } - - public function getTrigram() - { - return $this->trigram; - } - - public function setTrigram($trigram) - { - global $DB; - $this->trigram = $trigram; - $DB->prepare("UPDATE `teams` SET `trigram` = ? WHERE `id` = ?;")->execute([$trigram, $this->id]); - } - - public function getProblem() - { - return $this->problem; - } - - public function setProblem($problem) - { - global $DB; - $this->problem = $problem; - $DB->prepare("UPDATE `teams` SET `problem` = ? WHERE `id` = ?;")->execute([$problem, $this->id]); - } - - public function getEncadrantId() - { - return $this->encadrant; - } - - public function setEncadrant($encadrant) - { - global $DB; - $this->encadrant = $encadrant; - /** @noinspection SqlResolve */ - $DB->prepare("UPDATE `teams` SET `encadrant` = ? WHERE `id` = ?;")->execute([$encadrant, $this->id]); - } - - public function getParticipants() - { - return $this->participants; - } - - public function setParticipant($i, $participant) - { - global $DB; - $this->participants[$i - 1] = $participant; - /** @noinspection SqlResolve */ - $DB->prepare("UPDATE `teams` SET `participant_$i` = ? WHERE `id` = ?;")->execute([$participant, $this->id]); - } - - public function getInscriptionDate() - { - return $this->inscription_date; - } - - public function allowPublish() - { - return $this->allow_publish; - } - - public function setAllowPublish($allow_publish) - { - global $DB; - $this->allow_publish = $allow_publish; - $DB->prepare("UPDATE `teams` SET `allow_publish` = ? WHERE `id` = ?;")->execute([$allow_publish ? 1 : 0, $this->id]); - } - - public function getValidationStatus() - { - return $this->validation_status; - } - - public function setValidationStatus($status) - { - global $DB; - $this->validation_status = $status; - $DB->prepare("UPDATE `teams` SET `validation_status` = ? WHERE `id` = ?;")->execute([ValidationStatus::getName($status), $this->id]); - } - - public function getSolution() - { - return Video::getVideo(Reason::SOLUTION, $this); - } - - public function getVideoTeamIds() - { - return $this->video_team_ids; - } - - public function setVideoTeamIds($video_team_ids) - { - global $DB; - ensure(sizeof($video_team_ids) == 2, "Une équipe doit recevoir exactement deux vidéos."); - $this->video_team_ids = $video_team_ids; - $DB->prepare("UPDATE `teams` SET `video_team1` = ?, `video_team2` = ? WHERE `id` = ?;")->execute([$video_team_ids[0], $video_team_ids[1], $this->id]); - } - - public function getAccessCode() - { - return $this->access_code; - } - - public function getYear() - { - return $this->year; - } - - public function getAllDocuments() - { - global $DB; - $req = $DB->query("SELECT * FROM `documents` AS `t1` " - . "INNER JOIN (SELECT `team`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`user`) AS `version` FROM `documents` GROUP BY `problem`, `user`, `team`) `t2` " - . "ON `t1`.`team` = `t2`.`team` " - . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`team` = $this->id;"); - - $docs = []; - - while (($data = $req->fetch()) !== false) - $docs[] = Document::fromData($data); - - return $docs; - } - - public function getAllEmails() - { - $emails = []; - if ($this->getEncadrantId() != null) - $emails[] = User::fromId($this->getEncadrantId())->getEmail(); - - foreach ($this->getParticipants() as $participantId) { - if ($participantId != 0) - $emails[] = User::fromId($participantId)->getEmail(); - } - - return $emails; - } -} diff --git a/server_files/classes/User.php b/server_files/classes/User.php deleted file mode 100644 index b81bd99..0000000 --- a/server_files/classes/User.php +++ /dev/null @@ -1,335 +0,0 @@ -prepare("SELECT * FROM `users` WHERE `id` = ?;"); - $req->execute([htmlspecialchars($id)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $user = new User(); - $user->fill($data); - return $user; - } - - public static function fromEmail($email) - { - global $DB, $YEAR; - $req = $DB->prepare("SELECT * FROM `users` WHERE `email` = ? AND `year` = $YEAR;"); - $req->execute([htmlspecialchars($email)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $user = new User(); - $user->fill($data); - return $user; - } - - public static function getAdmins() - { - global $DB, $YEAR; - $admins = []; - $req = $DB->query("SELECT * FROM `users` WHERE `role` = 'ADMIN' AND `year` = $YEAR;"); - - while (($data = $req->fetch()) !== false) { - $admin = new User(); - $admin->fill($data); - $admins[] = $admin; - } - - return $admins; - } - - public static function getAllUsers() - { - global $DB, $YEAR; - $orphans = []; - $req = $DB->query("SELECT * FROM `users` WHERE `role` != 'ADMIN' AND `year` = $YEAR ORDER BY `role`, `inscription_date`;"); - - while (($data = $req->fetch()) !== false) { - $orphan = new User(); - $orphan->fill($data); - $orphans[] = $orphan; - } - - return $orphans; - } - - public static function getOrphanUsers() - { - global $DB, $YEAR; - $orphans = []; - $req = $DB->query("SELECT * FROM `users` WHERE `role` != 'ADMIN' AND `team_id` IS NULL " - . "AND NOT EXISTS (SELECT 1 FROM `teams` WHERE `encadrant` = `users`.`id`) " - . "AND `year` = $YEAR ORDER BY `role`, `inscription_date`;"); - - while (($data = $req->fetch()) !== false) { - $orphan = new User(); - $orphan->fill($data); - $orphans[] = $orphan; - } - - return $orphans; - } - - private function fill($data) - { - $this->id = $data["id"]; - $this->email = $data["email"]; - $this->pwd_hash = $data["pwd_hash"]; - $this->surname = $data["surname"]; - $this->first_name = $data["first_name"]; - $this->school = $data["school"]; - $this->city = $data["city"]; - $this->country = $data["country"]; - $this->class = SchoolClass::fromName($data["class"]); - $this->description = $data["description"]; - $this->role = Role::fromName($data["role"]); - $this->team_id = $data["team_id"]; - $this->year = $data["year"]; - $this->confirm_email = $data["confirm_email"]; - $this->forgotten_password = $data["forgotten_password"]; - $this->inscription_date = $data["inscription_date"]; - $this->receive_animath_mails = $data["receive_animath_mails"]; - } - - public function getEmail() - { - return $this->email; - } - - public function setEmail($email) - { - global $DB; - $this->email = $email; - $DB->prepare("UPDATE `users` SET `email` = ? WHERE `id` = ?;")->execute([$email, $this->getId()]); - } - - public function getId() - { - return $this->id; - } - - public function checkPassword($password) - { - return password_verify($password, $this->pwd_hash); - } - - public function setPassword($password) - { - $this->setPasswordHash(password_hash($password, PASSWORD_BCRYPT)); - } - - private function setPasswordHash($password_hash) - { - global $DB; - $this->pwd_hash = $password_hash; - $DB->prepare("UPDATE `users` SET `pwd_hash` = ? WHERE `id` = ?;")->execute([$password_hash, $this->getId()]); - } - - public function getSurname() - { - return $this->surname; - } - - public function setSurname($surname) - { - global $DB; - $this->surname = $surname; - $DB->prepare("UPDATE `users` SET `surname` = ? WHERE `id` = ?;")->execute([$surname, $this->getId()]); - } - - public function getFirstName() - { - return $this->first_name; - } - - public function setFirstName($first_name) - { - global $DB; - $this->first_name = $first_name; - $DB->prepare("UPDATE `users` SET `first_name` = ? WHERE `id` = ?;")->execute([$first_name, $this->getId()]); - } - - public function getSchool() - { - return $this->school; - } - - public function setSchool($school) - { - global $DB; - $this->school = $school; - $DB->prepare("UPDATE `users` SET `school` = ? WHERE `id` = ?;")->execute([$school, $this->getId()]); - } - - public function getCity() - { - return $this->city; - } - - public function setCity($city) - { - global $DB; - $this->city = $city; - $DB->prepare("UPDATE `users` SET `city` = ? WHERE `id` = ?;")->execute([$city, $this->getId()]); - } - - public function getCountry() - { - return $this->country; - } - - public function setCountry($country) - { - global $DB; - $this->country = $country; - $DB->prepare("UPDATE `users` SET `country` = ? WHERE `id` = ?;")->execute([$country, $this->getId()]); - } - - public function getClass() - { - return $this->class; - } - - public function setClass($class) - { - global $DB; - $this->class = $class; - $DB->prepare("UPDATE `users` SET `class` = ? WHERE `id` = ?;")->execute([SchoolClass::getName($class), $this->getId()]); - } - - public function getDescription() - { - return $this->description; - } - - public function setDescription($desc) - { - global $DB; - $this->description = $desc; - $DB->prepare("UPDATE `users` SET `description` = ? WHERE `id` = ?;")->execute([$desc, $this->getId()]); - } - - public function getRole() - { - return $this->role; - } - - public function setRole($role) - { - global $DB; - $this->role = $role; - $DB->prepare("UPDATE `users` SET `role` = ? WHERE `id` = ?;")->execute([Role::getName($role), $this->getId()]); - } - - public function getTeamId() - { - return $this->team_id; - } - - public function setTeamId($team_id) - { - global $DB; - $this->team_id = $team_id; - $DB->prepare("UPDATE `users` SET `team_id` = ? WHERE `id` = ?;")->execute([$team_id, $this->getId()]); - } - - public function getConfirmEmailToken() - { - return $this->confirm_email; - } - - public function setConfirmEmailToken($token) - { - global $DB; - $this->confirm_email = $token; - $DB->prepare("UPDATE `users` SET `confirm_email` = ? WHERE `id` = ?;")->execute([$token, $this->getId()]); - } - - public function getForgottenPasswordToken() - { - return $this->forgotten_password; - } - - public function setForgottenPasswordToken($token) - { - global $DB; - $this->forgotten_password = $token; - $DB->prepare("UPDATE `users` SET `forgotten_password` = ? WHERE `id` = ?;")->execute([$token, $this->getId()]); - } - - public function getInscriptionDate() - { - return $this->inscription_date; - } - - public function doReceiveAnimathMails() - { - return $this->receive_animath_mails; - } - - public function setReceiveAnimathMails($receive_animath_mails) - { - global $DB; - $this->receive_animath_mails = $receive_animath_mails; - $DB->prepare("UPDATE `users` SET `receive_animath_mails` = ? WHERE `id` = ?;")->execute([$receive_animath_mails ? 1 : 0, $this->getId()]); - } - - public function getAllDocuments() - { - global $DB; - $req = $DB->query("SELECT * FROM `documents` AS `t1` " - . "INNER JOIN (SELECT `user`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `problem`, `user`) `t2` " - . "ON `t1`.`user` = `t2`.`user` " - . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`user` = $this->id;"); - - $docs = []; - - while (($data = $req->fetch()) !== false) - $docs[] = Document::fromData($data); - - return $docs; - } - - // Seulement pour les encadrants - public function getTeams() - { - global $DB; - $req = $DB->query("SELECT `id` FROM `teams` WHERE `encadrant` = $this->id OR `participant_1` = $this->id OR `participant_2` = $this->id OR `participant_3` = $this->id OR `participant_4` = $this->id OR `participant_5` = $this->id;"); - - $teams = []; - - while (($data =$req->fetch()) !== false) - $teams[] = Team::fromId($data["id"]); - - return $teams; - } -} \ No newline at end of file diff --git a/server_files/classes/ValidationStatus.php b/server_files/classes/ValidationStatus.php deleted file mode 100644 index 459d7ad..0000000 --- a/server_files/classes/ValidationStatus.php +++ /dev/null @@ -1,41 +0,0 @@ -prepare("SELECT * FROM `videos` WHERE `id` = ?;"); - $req->execute([htmlspecialchars($id)]); - $data = $req->fetch(); - - if ($data === false) - return null; - - $video = new Video(); - $video->fill($data); - return $video; - } - - public static function getVideos($reason, $problem, $validation_min = -1, $team_id = -1) - { - global $DB, $YEAR; - $req = $DB->query("SELECT * FROM `videos` AS `t1` " - . "INNER JOIN (SELECT `team`, `problem`, `reason`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `videos` " - . "WHERE `validation` >= $validation_min AND `year` = $YEAR GROUP BY `problem`, `reason`, `team`) `t2` " - . "ON `t1`.`team` = `t2`.`team` AND `t1`.`reason` = `t2`.`reason` AND `t1`.`problem` = `t2`.`problem` " - . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`problem` = $problem AND `t1`.`reason` = '" . Reason::getName($reason) . "'" - . ($team_id >= 0 ? " AND `t1`.`team` = $team_id" : "") - . " AND `validation` >= $validation_min AND `year` = $YEAR ORDER BY `t1`.`problem`, `t1`.`reason`;"); - - $videos = []; - - while (($data = $req->fetch()) !== false) { - $video = new Video(); - $video->fill($data); - $videos[] = $video; - } - - return $videos; - } - - /** - * @param int $reason - * @param Team $team - * @param int $validation_min - * @return Video|null - */ - public static function getVideo($reason, Team $team, $validation_min = -1) { - $videos = self::getVideos($reason, $team->getProblem(), $validation_min, $team->getId()); - if (sizeof($videos) == 0) - return null; - else - return $videos[0]; - } - - private function fill($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - - $this->reason = Reason::fromName($this->reason); - } - - public function getId() - { - return $this->id; - } - - public function getTeam() - { - return $this->team; - } - - public function getProblem() - { - return $this->problem; - } - - public function getLink() - { - return $this->link; - } - - public function getReason() - { - return $this->reason; - } - - public function getValidation() - { - return $this->validation; - } - - public function setValidation($validation) - { - global $DB; - $this->validation = $validation; - $DB->exec("UPDATE `videos` SET `validation` = $validation WHERE `id` = $this->id;"); - } - - public function getUploadedAt() - { - return $this->uploaded_at; - } - - public function getYear() - { - return $this->year; - } - - public function getVersion() - { - return $this->version; - } -} \ No newline at end of file diff --git a/server_files/config.php b/server_files/config.php deleted file mode 100644 index 155f878..0000000 --- a/server_files/config.php +++ /dev/null @@ -1,227 +0,0 @@ - PDO::ERRMODE_EXCEPTION)); -} -catch (Exception $ex) { - die("Erreur lors de la connexion à la base de données : " . $ex->getMessage()); -} - -$CONFIG = new Config(); -$CONFIG->initDB(); -$CONFIG->loadConfigValues(); - -class Config -{ - private $inscription_date; - private $start_phase1_date; - private $end_phase1_date; - private $start_phase2_date; - private $end_phase2_date; - private $start_phase3_date; - private $end_phase3_date; - private $start_phase4_date; - private $end_phase4_date; - private $index_page; - private $views; - - public function initDB() - { - global $DB, $LOCAL_PATH, $YEAR; - - $index_template_page = htmlspecialchars(file_get_contents($LOCAL_PATH . "/server_files/views/index.html")); - - $DB->exec("SET GLOBAL time_zone = 'Europe/Paris';"); - $DB->prepare("INSERT IGNORE INTO `config`(`key`, `value`) - VALUES ('inscription_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 2 DAY), - ('start_phase1_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 1 DAY), - ('end_phase1_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 3 DAY), - ('start_phase2_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 4 DAY), - ('end_phase2_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 5 DAY), - ('start_phase3_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 6 DAY), - ('end_phase3_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 7 DAY), - ('start_phase4_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 8 DAY), - ('end_phase4_date_$YEAR', CURRENT_TIMESTAMP + INTERVAL 9 DAY), - ('index_page_$YEAR', ?), - ('views_$YEAR', 0);")->execute([$index_template_page]); - } - - public function loadConfigValues() - { - global $DB, $YEAR; - - $req = $DB->query("SELECT * FROM `config` WHERE `key` REGEXP '$YEAR';"); - - while (($data = $req->fetch()) !== false) { - $key = substr($data["key"], 0, -5); - $this->$key = $data["value"]; - } - } - - public function getInscriptionDate() - { - return $this->inscription_date; - } - - public function setInscriptionDate($inscription_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$inscription_date' WHERE `key` = 'inscription_date_$YEAR'"); - - $this->inscription_date = $inscription_date; - } - - public function getStartPhase1Date() - { - return $this->start_phase1_date; - } - - public function setStartPhase1Date($start_phase1_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$start_phase1_date' WHERE `key` = 'start_phase1_date_$YEAR'"); - - $this->start_phase1_date = $start_phase1_date; - } - - public function getEndPhase1Date() - { - return $this->end_phase1_date; - } - - public function setEndPhase1Date($end_phase1_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$end_phase1_date' WHERE `key` = 'end_phase1_date_$YEAR'"); - - $this->end_phase1_date = $end_phase1_date; - } - - public function getStartPhase2Date() - { - return $this->start_phase2_date; - } - - public function setStartPhase2Date($start_phase2_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$start_phase2_date' WHERE `key` = 'start_phase2_date_$YEAR'"); - - $this->start_phase2_date = $start_phase2_date; - } - - public function getEndPhase2Date() - { - return $this->end_phase2_date; - } - - public function setEndPhase2Date($end_phase2_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$end_phase2_date' WHERE `key` = 'end_phase2_date_$YEAR'"); - - $this->end_phase2_date = $end_phase2_date; - } - - public function getStartPhase3Date() - { - return $this->start_phase3_date; - } - - public function setStartPhase3Date($start_phase3_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$start_phase3_date' WHERE `key` = 'start_phase3_date_$YEAR'"); - - $this->start_phase3_date = $start_phase3_date; - } - - public function getEndPhase3Date() - { - return $this->end_phase3_date; - } - - public function setEndPhase3Date($end_phase3_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$end_phase3_date' WHERE `key` = 'end_phase3_date_$YEAR'"); - - $this->end_phase3_date = $end_phase3_date; - } - - public function getStartPhase4Date() - { - return $this->start_phase4_date; - } - - public function setStartPhase4Date($start_phase4_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$start_phase4_date' WHERE `key` = 'start_phase4_date_$YEAR'"); - - $this->start_phase4_date = $start_phase4_date; - } - - public function getEndPhase4Date() - { - return $this->end_phase4_date; - } - - public function setEndPhase4Date($end_phase4_date) - { - global $DB, $YEAR; - $DB->exec("UPDATE `config` SET `value` = '$end_phase4_date' WHERE `key` = 'end_phase4_date_$YEAR'"); - - $this->end_phase4_date = $end_phase4_date; - } - - public function getIndexPage() - { - return $this->index_page; - } - - public function setIndexPage($index_page) - { - global $DB, $YEAR; - $DB->prepare("UPDATE `config` SET `value` = ? WHERE `key` = 'index_page_$YEAR'")->execute([$index_page]); - - $this->index_page = $index_page; - } - - public function getViews() - { - return $this->views; - } - - public function incrViews() - { - global $DB, $YEAR; - - if (isset($_SESSION["user_id"]) && $_SESSION["role"] == Role::ADMIN || isset($_SESSION["admin"])) - return; - - $DB->exec("UPDATE `config` SET `value` = " . ($this->views + 1) . " WHERE `key` = 'views_$YEAR';"); - $this->views++; - } -} - -session_start(); -setlocale(LC_ALL, "fr_FR.utf8"); -date_default_timezone_set("Europe/Paris"); diff --git a/server_files/controllers/admins.php b/server_files/controllers/admins.php deleted file mode 100644 index 23ece61..0000000 --- a/server_files/controllers/admins.php +++ /dev/null @@ -1,8 +0,0 @@ -makeVerifications(); - $admin->register(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class NewAdmin { - public $surname; - public $first_name; - public $email; - public $password; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - } - - public function makeVerifications() - { - ensure($this->surname != null && $this->surname != "", "Le nom est invalide."); - ensure($this->first_name != null && $this->first_name != "", "Le prénom est invalide."); - ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail est invalide."); - $this->email = strtolower($this->email); - ensure(!userExists($this->email), "Cette adresse e-mail est déjà utilisée."); - } - - public function register() { - global $DB, $YEAR; - - $this->password = genRandomPhrase(16, true); - - $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `surname`, `first_name`, `class`, `role`, `year`) - VALUES (?, ?, ?, ?, ?, ?, ?);"); - $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->surname, - $this->first_name, "ADULT", "ADMIN", $YEAR]); - - Mailer::sendAddAdminMail($this); - } -} - -require_once "server_files/views/ajouter_admin.php"; \ No newline at end of file diff --git a/server_files/controllers/ajouter_equipe.php b/server_files/controllers/ajouter_equipe.php deleted file mode 100644 index 234d341..0000000 --- a/server_files/controllers/ajouter_equipe.php +++ /dev/null @@ -1,75 +0,0 @@ -makeVerifications(); - $new_team->register(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class NewTeam { - public $name; - public $trigram; - public $problem; - public $allow_other_teams; - public $allow_publish; - public $access_code; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - - $this->trigram = strtoupper($this->trigram); - - $this->allow_other_teams = $this->allow_other_teams == "on" ? 1 : 0; - $this->allow_publish = $this->allow_publish == "on" ? 1 : 0; - } - - public function makeVerifications() { - global $CONFIG; - - ensure(date("Y-m-d H:i:s") < $CONFIG->getInscriptionDate(), "La date limite d'inscription est dépassée."); - ensure($_SESSION["team"] == null || $_SESSION["role"] == Role::ENCADRANT, "Vous êtes déjà dans une équipe."); - ensure($this->name != null && $this->name != "", "Vous devez spécifier un nom d'équipe."); - ensure(preg_match("#^[\p{L} ]+$#ui", $this->name), "Le nom de l'équipe ne doit pas comporter de caractères spéciaux."); - ensure(preg_match("#^[A-Z]{3}$#", $this->trigram), "Le trigramme entré n'est pas valide."); - ensure(!teamExists($this->name), "Une équipe existe déjà avec ce nom."); - ensure(!trigramExists($this->trigram), "Une équipe a déjà choisi ce trigramme."); - ensure(preg_match("#[0-4]#", $this->problem), "Le problème choisi n'a pas été reconnu."); - ensure($this->allow_other_teams, "Vous devez autoriser de diffuser vos vidéos aux autres équipes participantes pour pouvoir participer."); - } - - public function register() { - global $DB, $YEAR; - - $this->access_code = genRandomPhrase(6); - - $req = $DB->prepare("INSERT INTO `teams` (`name`, `trigram`, `problem`, `encadrant`, `participant_1`, `allow_publish`, `validation_status`, `access_code`, `year`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);"); - $req->execute([$this->name, $this->trigram, $this->problem, $_SESSION["role"] == Role::ENCADRANT ? $_SESSION["user_id"] : NULL, - $_SESSION["role"] == Role::PARTICIPANT ? $_SESSION["user_id"] : NULL, $this->allow_publish, ValidationStatus::getName(ValidationStatus::NOT_READY), $this->access_code, $YEAR]); - - $_SESSION["teams"] = $_SESSION["user"]->getTeams(); - $team = Team::fromTrigram($this->trigram); - if ($_SESSION["role"] == Role::PARTICIPANT) { - $_SESSION["team"] = $team; - $_SESSION["user"]->setTeamId($_SESSION["team"]->getId()); - } - - Mailer::sendAddTeamMail($_SESSION["user"], $team); - } -} - -require_once "server_files/views/ajouter_equipe.php"; diff --git a/server_files/controllers/calendrier.php b/server_files/controllers/calendrier.php deleted file mode 100644 index 1db0176..0000000 --- a/server_files/controllers/calendrier.php +++ /dev/null @@ -1,76 +0,0 @@ -makeVerifications(); - $update_calendar->updateCalendar(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class UpdateCalendar -{ - private $date_inscription; - private $time_inscription; - private $date_start_phase1; - private $time_start_phase1; - private $date_end_phase1; - private $time_end_phase1; - private $date_start_phase2; - private $time_start_phase2; - private $date_end_phase2; - private $time_end_phase2; - private $date_start_phase3; - private $time_start_phase3; - private $date_end_phase3; - private $time_end_phase3; - private $date_start_phase4; - private $time_start_phase4; - private $date_end_phase4; - private $time_end_phase4; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - } - - public function makeVerifications() - { - ensure(dateWellFormed($this->date_inscription . " " . $this->time_inscription), "La date d'inscription n'est pas bien formée."); - ensure(dateWellFormed($this->date_start_phase1 . " " . $this->time_start_phase1), "La date de début de la phase 1 n'est pas bien formée."); - ensure(dateWellFormed($this->date_end_phase1 . " " . $this->time_end_phase1), "La date de fin de la phase 1 n'est pas bien formée."); - ensure(dateWellFormed($this->date_start_phase2 . " " . $this->time_start_phase2), "La date de début de la phase 2 n'est pas bien formée."); - ensure(dateWellFormed($this->date_end_phase2 . " " . $this->time_end_phase2), "La date de fin de la phase 2 n'est pas bien formée."); - ensure(dateWellFormed($this->date_start_phase3 . " " . $this->time_start_phase3), "La date de début de la phase 3 n'est pas bien formée."); - ensure(dateWellFormed($this->date_end_phase3 . " " . $this->time_end_phase3), "La date de fin de la phase 3 n'est pas bien formée."); - ensure(dateWellFormed($this->date_start_phase4 . " " . $this->time_start_phase4), "La date de début de la phase 4 n'est pas bien formée."); - ensure(dateWellFormed($this->date_end_phase4 . " " . $this->time_end_phase4), "La date de fin de la phase 4 n'est pas bien formée."); - } - - public function updateCalendar() - { - global $CONFIG, $URL_BASE; - - $CONFIG->setInscriptionDate($this->date_inscription . " " . $this->time_inscription); - $CONFIG->setStartPhase1Date($this->date_start_phase1 . " " . $this->time_start_phase1); - $CONFIG->setEndPhase1Date($this->date_end_phase1 . " " . $this->time_end_phase1); - $CONFIG->setStartPhase2Date($this->date_start_phase2 . " " . $this->time_start_phase2); - $CONFIG->setEndPhase2Date($this->date_end_phase2 . " " . $this->time_end_phase2); - $CONFIG->setStartPhase3Date($this->date_start_phase3 . " " . $this->time_start_phase3); - $CONFIG->setEndPhase3Date($this->date_end_phase3 . " " . $this->time_end_phase3); - $CONFIG->setStartPhase4Date($this->date_start_phase4 . " " . $this->time_start_phase4); - $CONFIG->setEndPhase4Date($this->date_end_phase4 . " " . $this->time_end_phase4); - - header("Location: $URL_BASE/calendrier"); - exit(); - } -} - -require_once "server_files/views/calendrier.php"; \ No newline at end of file diff --git a/server_files/controllers/commenter_echange.php b/server_files/controllers/commenter_echange.php deleted file mode 100644 index b1f3e92..0000000 --- a/server_files/controllers/commenter_echange.php +++ /dev/null @@ -1,77 +0,0 @@ -getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - -if ($team == null) - require_once "server_files/404.php"; - -if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId() || $team->getValidationStatus() != ValidationStatus::VALIDATED) - require_once "server_files/403.php"; - -if (isset($_POST["upload_answer"])) { - $new_answer = new NewAnswer($_POST); - try { - $new_answer->makeVerifications(); - $new_answer->uploadVideo(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class NewAnswer -{ - public $link; - public $team; - private $valid_link; - private $no_change; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - } - - public function makeVerifications() - { - ensure(preg_match("#(https?\:\/\/|)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?#", $this->link), "Ce n'est pas une URL valide."); - $this->link = preg_replace('/^(?!https?:\/\/)/', 'https://', $this->link); - ensure(preg_match("#[1|2]#", $this->team), "L'équipe n'a pas été trouvée."); - ensure($this->valid_link != null, "Vous devez confirmer que le lien est valide."); - ensure($this->no_change != null, "Vous devez vous engager à ne pas changer le contenu du lien et de la vidéo."); - } - - public function uploadVideo() - { - global $DB, $YEAR, $team; - - $req = $DB->prepare("INSERT INTO `videos`(`team`, `problem`, `link`, `reason`, `year`) VALUES (?, ?, ?, ?, ?)"); - $req->execute([$team->getId(), $team->getProblem(), $this->link, "ANSWER" . $this->team, $YEAR]); - - Mailer::sendNewAnswer($this, $team); - } -} - -$team1 = Team::fromId($team->getVideoTeamIds()[0]); -$sol1 = Video::getVideo(Reason::SOLUTION, $team1); -$answer1 = Video::getVideo(Reason::ANSWER1, $team); -$answer1_validated = Video::getVideo(Reason::ANSWER1, $team, Video::ACCEPTED); -$team2 = Team::fromId($team->getVideoTeamIds()[1]); -$sol2 = Video::getVideo(Reason::SOLUTION, $team2); -$answer2 = Video::getVideo(Reason::ANSWER2, $team); -$answer2_validated = Video::getVideo(Reason::ANSWER2, $team, Video::ACCEPTED); - -$teams = [$team1, $team2]; -$sols = [$sol1, $sol2]; -$answers = [$answer1, $answer2]; -$answers_validated = [$answer1_validated, $answer2_validated]; - -require_once "server_files/views/commenter_echange.php"; \ No newline at end of file diff --git a/server_files/controllers/confirmer_mail.php b/server_files/controllers/confirmer_mail.php deleted file mode 100644 index ea06f20..0000000 --- a/server_files/controllers/confirmer_mail.php +++ /dev/null @@ -1,25 +0,0 @@ -query("SELECT `email` FROM `users` WHERE `confirm_email` = '$token' AND `year` = '$YEAR';"); - if (($data = $result->fetch()) === FALSE) { - $has_error = true; - $error_message = "Le jeton est invalide. Votre compte est peut-être déjà validé ?"; - } - else { - $DB->exec("UPDATE `users` SET `confirm_email` = NULL WHERE `confirm_email` = '$token';"); - $error_message = "Votre adresse mail a été validée ! Vous pouvez désormais vous connecter."; - } -} -else { - $has_error = true; - $error_message = "Il n'y a pas de compte à valider !"; -} -require_once "server_files/views/header.php"; -if (!$has_error) -echo "
$error_message
"; -require_once "server_files/views/footer.php"; diff --git a/server_files/controllers/connexion.php b/server_files/controllers/connexion.php deleted file mode 100644 index 9a441c8..0000000 --- a/server_files/controllers/connexion.php +++ /dev/null @@ -1,170 +0,0 @@ -makeVerifications(); - $logging_in_user->login(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_POST["forgotten_password"]) && !isset($_SESSION["user_id"])) { - $recuperate_account = new RecuperateAccount($_POST); - try { - $recuperate_account->makeVerifications(); - $recuperate_account->recuperateAccount(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_GET["reset_password"]) && isset($_GET["token"]) && !isset($_SESSION["user_id"])) { - $reset_password = new ResetPassword($_GET, $_POST); - try { - $reset_password->makeVerifications(); - if (isset($_POST["password"])) - $reset_password->resetPassword(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_GET["confirmation-mail"]) && !isset($_SESSION["user_id"])) - sendConfirmEmail(); - -class LoggingInUser -{ - public $email; - /** @var User $user */ - public $user; - private $password; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - } - - public function makeVerifications() - { - ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse email est invalide."); - $this->user = User::fromEmail($this->email); - ensure($this->user != null, "Le compte n'existe pas."); - ensure($this->user->checkPassword($this->password), "Le mot de passe est incorrect."); - if ($this->user->getConfirmEmailToken() != null) { - $_SESSION["confirm_email"] = $this->email; - /** @noinspection HtmlUnknownTarget */ - throw new AssertionError("L'adresse mail n'a pas été validée. Veuillez vérifier votre boîte mail (surtout vos spams). " - . "Cliquez ici pour renvoyer le mail de confirmation."); - } - } - - public function login() - { - $_SESSION["user_id"] = $this->user->getId(); - $this->user->setForgottenPasswordToken(null); - loadUserValues(); - } -} - -class RecuperateAccount -{ - public $email; - /** @var User $user */ - public $user; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - } - - public function makeVerifications() - { - ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse email est invalide."); - $this->user = User::fromEmail($this->email); - ensure($this->user != null, "Le compte n'existe pas."); - } - - public function recuperateAccount() - { - $token = genRandomPhrase(64); - $this->user->setForgottenPasswordToken($token); - Mailer::sendForgottenPasswordProcedureMail($this->user); - } -} - -class ResetPassword -{ - public $token; - /** @var User $user */ - public $user; - private $password; - private $confirm_password; - - public function __construct($data, $data2) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - foreach ($data2 as $key => $value) - $this->$key = htmlspecialchars($value); - } - - public function makeVerifications() - { - global $DB; - $data = $DB->query("SELECT `id` FROM `users` WHERE `forgotten_password` = '" . $this->token . "';")->fetch(); - ensure($data !== false, "Il n'y a pas de compte à récupérer avec ce jeton."); - $this->user = User::fromId($data["id"]); - - if (!isset($_POST["password"])) - return; - - ensure($this->password == $this->confirm_password, "Les deux mots de passe sont différents."); - ensure(strlen($this->password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); - } - - public function resetPassword() - { - $this->user->setForgottenPasswordToken(null); - $this->user->setPassword($this->password); - - Mailer::sendChangePasswordMail($this->user); - - return false; - } -} - -function sendConfirmEmail() -{ - global $URL_BASE; - - $email = htmlspecialchars($_SESSION["confirm_email"]); - - if (!isset($email)) { - header("Location: $URL_BASE/connexion"); - exit(); - } - - $user = User::fromEmail($email); - - if ($user === null) { - unset($_SESSION["confirm_email"]); - header("Location: $URL_BASE/connexion"); - exit(); - } - - Mailer::sendConfirmEmail($user); - - return false; -} - -require_once "server_files/views/connexion.php"; diff --git a/server_files/controllers/deconnexion.php b/server_files/controllers/deconnexion.php deleted file mode 100644 index 20e215e..0000000 --- a/server_files/controllers/deconnexion.php +++ /dev/null @@ -1,14 +0,0 @@ - - -
- Déconnexion réussie ! -
- -getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - -if ($team == null) - require_once "server_files/404.php"; - -if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId() || $team->getValidationStatus() != ValidationStatus::VALIDATED) - require_once "server_files/403.php"; - -if (Phase::getCurrentPhase() != Phase::PHASE1) { - if (!(Phase::getCurrentPhase() == Phase::PHASE12 && Video::getVideo(Reason::SOLUTION, $team) != NULL && (Video::getVideo(Reason::SOLUTION, $team, ValidationStatus::WAITING) == NULL || isset($_POST["upload"])))) - require_once "server_files/403.php"; -} - -$has_error = false; -$error_message = null; - -if (isset($_POST["upload"])) { - $new_video = new NewVideo($_POST); - try { - $new_video->makeVerifications(); - $new_video->uploadVideo(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class NewVideo -{ - public $link; - private $valid_link; - private $no_change; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - } - - public function makeVerifications() - { - ensure(preg_match("#(https?\:\/\/|)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(\/\S*)?#", $this->link), "Ce n'est pas une URL valide."); - $this->link = preg_replace('/^(?!https?:\/\/)/', 'https://', $this->link); - ensure($this->valid_link != null, "Vous devez confirmer que le lien est valide."); - ensure($this->no_change != null, "Vous devez vous engager à ne pas changer le contenu du lien et de la vidéo."); - } - - public function uploadVideo() - { - global $DB, $YEAR, $team; - - $req = $DB->prepare("INSERT INTO `videos`(`team`, `problem`, `link`, `reason`, `year`) VALUES (?, ?, ?, ?, ?)"); - $req->execute([$team->getId(), $team->getProblem(), $this->link, Reason::getName(Reason::SOLUTION), $YEAR]); - - Mailer::sendNewVideo($this, $team); - } -} - -$video = Video::getVideo(Reason::SOLUTION, $team); -$video_validated = Video::getVideo(Reason::SOLUTION, $team, Video::ACCEPTED); - -require_once "server_files/views/envoyer_video.php"; \ No newline at end of file diff --git a/server_files/controllers/equipe.php b/server_files/controllers/equipe.php deleted file mode 100644 index 2f226b1..0000000 --- a/server_files/controllers/equipe.php +++ /dev/null @@ -1,112 +0,0 @@ -setValidationStatus(ValidationStatus::VALIDATED); - Mailer::sendValidateTeam($team, $_POST["message"]); -} -elseif (isset($_POST["unvalidate"])) { - $team->setValidationStatus(ValidationStatus::NOT_READY); - Mailer::sendUnvalidateTeam($team, $_POST["message"]); -} -elseif (isset($_POST["select_problem"])) { - if ($team->getValidationStatus() == ValidationStatus::NOT_READY) { - $problem = $_POST["select_problem"]; - if (preg_match("#[0-4]#", $problem)) { - $team->setProblem($problem); - $DB->prepare("UPDATE `documents` SET `problem` = ? WHERE `team` = ?;")->execute([$problem, $team->getId()]); - } - else { - $has_error = true; - $error_message = "Le problème indiqué n'existe pas."; - } - } - else { - $has_error = true; - $error_message = "Cette équipe est déjà validée ou en cours de validation."; - } -} -elseif (isset($_POST["delete_team"])) { - if ($team->getValidationStatus() == ValidationStatus::NOT_READY) { - $documents = Document::getAllDocuments($team->getProblem(), $team->getId()); - /** @var Document $doc */ - foreach ($documents as $doc) - unlink($LOCAL_PATH . "/files/" . $doc->getFileId()); - $DB->prepare("DELETE FROM `documents` WHERE `team` = ?;")->execute([$team->getId()]); - $DB->prepare("DELETE FROM `teams` WHERE `id` = ?;")->execute([$team->getId()]); - $DB->prepare("UPDATE `users` SET `team_id` = NULL WHERE `team_id` = ?;")->execute([$team->getId()]); - header("Location: /"); - exit(0); - } - else { - $has_error = true; - $error_message = "Cette équipe est déjà validée ou en cours de validation."; - } -} - -if (isset($_POST["download_zip"])) { - $file_name = getZipFile($team->getProblem(), $team->getId()); - - header("Content-Type: application/zip"); - header("Content-Disposition: attachment; filename=\"Documents de l'équipe " . $team->getTrigram() . ".zip\""); - header("Content-Length: " . strval(filesize($file_name))); - - readfile($file_name); - - exit(); -} - -if (isset($_POST["update_video_teams"])) { - $update_video_teams = new UpdateVideoTeams($_POST); - try { - $update_video_teams->makeVerifications(); - $update_video_teams->update(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class UpdateVideoTeams -{ - private $other_teams; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - } - - public function makeVerifications() - { - global $team; - - ensure(Phase::getCurrentPhase() <= Phase::PHASE2, "Il est trop tard pour réaffecter les vidéos aux équipes."); - ensure($team->getSolution() != null, "L'équipe doit avoir soumis une vidéo."); - ensure($team->getSolution()->getValidation() == ValidationStatus::VALIDATED - 1, "L'équipe doit avoir soumis une vidéo validée."); - ensure(sizeof($this->other_teams) == 2, "L'équipe doit recevoir exactement deux vidéos."); - ensure(Team::fromId($this->other_teams[0]) != null, "La première équipe n'existe pas."); - ensure(Team::fromId($this->other_teams[1]) != null, "La seconde équipe n'existe pas."); - } - - public function update() - { - global $team; - - $team->setVideoTeamIds($this->other_teams); - } -} - -$other_teams = Team::getAllTeams($team->getProblem(), true, true); -$documents = Document::getAllDocuments($team->getProblem(), $team->getId()); - -require_once "server_files/views/equipe.php"; diff --git a/server_files/controllers/exporter_donnees.php b/server_files/controllers/exporter_donnees.php deleted file mode 100644 index 71b786d..0000000 --- a/server_files/controllers/exporter_donnees.php +++ /dev/null @@ -1,42 +0,0 @@ -setIndexPage(htmlspecialchars($content)); - header("Location: /"); - exit(0); - } -} - -require_once "server_files/views/index.php"; diff --git a/server_files/controllers/informations.php b/server_files/controllers/informations.php deleted file mode 100644 index 370cfcf..0000000 --- a/server_files/controllers/informations.php +++ /dev/null @@ -1,117 +0,0 @@ -getId() != $_SESSION["user_id"]) - require_once "server_files/403.php"; -} - -if ($user === null) - require_once "server_files/404.php"; - -$teams = $user->getTeams(); -if ($user->getRole() == Role::PARTICIPANT) - $team = sizeof($teams) == 0 ? null : $teams[0]; - -$has_error = false; -$error_message = null; - -if (isset($_POST["kick"])) { - if (sizeof($teams) == null) { - $has_error = true; - $error_message = "La personne à expulser n'est dans aucune équipe."; - } - else { - quitTeam($id); - $team = null; - } -} - -if (isset($_POST["attribute_team"])) { - $attribute_team = new AttributeTeam($_POST); - try { - $attribute_team->makeVerifications(); - $attribute_team->attribute(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_POST["view_as"]) && $_SESSION["role"] == Role::ADMIN) { - if (!isset($_SESSION["admin"])) - $_SESSION["admin"] = $_SESSION["user_id"]; - $_SESSION["user_id"] = $user->getId(); - header("Location: /"); - exit(); -} - -if (isset($_POST["delete_account"]) && $team == null && $_SESSION["role"] == Role::ADMIN) { - /** @var Document $document */ - foreach ($user->getAllDocuments() as $document) - unlink($LOCAL_PATH . "/files/" . $document->getFileId()); - $DB->prepare("DELETE FROM `documents` WHERE `user` = ?;")->execute([$user->getId()]); - $DB->prepare("DELETE FROM `users` WHERE `id` = ?;")->execute([$user->getId()]); - header("Location: /"); - exit(); -} - -class AttributeTeam -{ - private $team_id; - private $team; - private $min_null_index; - - public function __construct($data) - { - $this->team_id = $data["team"]; - $this->team = Team::fromId($this->team_id); - } - - public function makeVerifications() - { - global $user; - - ensure($user->getConfirmEmailToken() == null, "Ce participant n'a pas encore validé son adresse e-mail."); - ensure($this->team_id != "no_team", "Vous n'avez pas choisi d'équipe."); - ensure($this->team != null, "Cette équipe n'existe pas."); - ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Cette équipe est déjà validée ou en cours de validation."); - - $role = $user->getRole(); - for ($i = 1; $i <= $role == Role::ENCADRANT ? 1 : 5; ++$i) { - if (($role == Role::PARTICIPANT ? $this->team->getParticipants()[$i - 1] : $this->team->getEncadrantId()) == NULL) - break; - } - - $this->min_null_index = $i; - - ensure($role == Role::PARTICIPANT && $this->min_null_index <= 5 || $role == Role::ENCADRANT && $this->min_null_index <= 2, - "Il n'y a plus de place pour vous dans l'équipe."); - } - - public function attribute() - { - global $user, $team; - - $user->setTeamId($this->team->getId()); - - if ($user->getRole() == Role::ENCADRANT) - $this->team->setEncadrant($user->getId()); - else - $this->team->setParticipant($this->min_null_index, $user->getId()); - - Mailer::sendJoinTeamMail($user, $this->team); - - $team = $this->team; - } -} - -if ($teams != null) - $documents = $user->getAllDocuments(); - -require_once "server_files/views/informations.php"; diff --git a/server_files/controllers/inscription.php b/server_files/controllers/inscription.php deleted file mode 100644 index 6a51fe0..0000000 --- a/server_files/controllers/inscription.php +++ /dev/null @@ -1,84 +0,0 @@ -makeVerifications(); - $user->register(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class NewUser -{ - public $email; - public $first_name; - public $surname; - public $role; - public $school; - public $city; - public $country; - public $class; - public $receive_animath_mails; - - public $description; - public $confirm_email_token; - private $password; - private $confirm_password; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - - $this->receive_animath_mails = $this->receive_animath_mails ? 1 : 0; - } - - public function makeVerifications() - { - global $CONFIG; - - ensure(date("Y-m-d H:i:s") < $CONFIG->getInscriptionDate(), "Les inscriptions sont terminées."); - ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail entrée est invalide."); - $this->email = strtolower($this->email); - ensure(!userExists($this->email), "Un compte existe déjà avec cette adresse e-mail."); - ensure(strlen($this->password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); - ensure($this->password == $this->confirm_password, "Les deux mots de passe sont différents."); - ensure($this->surname != "", "Le nom de famille est obligatoire."); - ensure($this->first_name != "", "Le prénom est obligatoire."); - $this->role = Role::fromName(strtoupper($this->role)); - ensure($this->role == Role::PARTICIPANT || $this->role == Role::ENCADRANT, "Vous devez être participant ou encadrant."); - - if ($this->role == Role::PARTICIPANT) - $this->class = SchoolClass::fromName(strtoupper($this->class)); - else - $this->class = SchoolClass::ADULT; - - $this->confirm_email_token = genRandomPhrase(64); - } - - public function register() - { - global $DB, $YEAR; - - if (!$DB->query("SELECT `id` FROM `users` WHERE `year` = $YEAR;")->fetch()) - $this->role = Role::ADMIN; - - $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `confirm_email`, `surname`, `first_name`, - `school`, `city`, `country`, `class`, `role`, `description`, `receive_animath_mails`, `year`) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); - $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->confirm_email_token, - $this->surname, $this->first_name, $this->school, $this->city, $this->country, SchoolClass::getName($this->class), - Role::getName($this->role), $this->description, $this->receive_animath_mails, $YEAR]); - - Mailer::sendRegisterMail($this); - } -} - -require_once "server_files/views/inscription.php"; diff --git a/server_files/controllers/ma_participation.php b/server_files/controllers/ma_participation.php deleted file mode 100644 index 6452ed1..0000000 --- a/server_files/controllers/ma_participation.php +++ /dev/null @@ -1,23 +0,0 @@ - 0) { - /** - * @var User $user - * @var Team team - */ - $user = $_SESSION["user"]; - $team = $user->getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - - if ($team == null) - require_once "server_files/404.php"; - - if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId()) - require_once "server_files/403.php"; - - $video = Video::getVideo(Reason::SOLUTION, $team); - $questions_received = Question::getQuestionsTo($team); -} -else - require_once "server_files/403.php"; - -require_once "server_files/views/ma_participation.php"; \ No newline at end of file diff --git a/server_files/controllers/mon_compte.php b/server_files/controllers/mon_compte.php deleted file mode 100644 index dc944e4..0000000 --- a/server_files/controllers/mon_compte.php +++ /dev/null @@ -1,177 +0,0 @@ -makeVerifications(); - $my_account->updateAccount(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_POST["update_password"])) { - $new_password = new NewPassword($_POST); - try { - $new_password->makeVerifications(); - $new_password->updatePassword(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -if (isset($_POST["send_document"])) { - $send_document = new SendDocument(); - try { - $send_document->makeVerifications(); - $send_document->sendDocument(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class MyAccount -{ - public $email; - public $surname; - public $first_name; - public $school; - public $city; - public $country; - public $class; - public $description; - public $receive_animath_mails; - /** @var User */ - private $user; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - - $this->user = $_SESSION["user"]; - - $keys = ["email", "surname", "first_name", "school", "class", "description"]; - - if ($this->user->getRole() == Role::PARTICIPANT) - $this->class = SchoolClass::fromName($this->class); - - foreach ($keys as $key) - $this->$key = $this->$key != null && $this->$key != "" ? $this->$key : $this->user->$key; - - $this->receive_animath_mails = $this->receive_animath_mails == "on"; - } - - public function makeVerifications() - { - ensure(filter_var($this->email, FILTER_VALIDATE_EMAIL), "L'adresse e-mail entrée est invalide."); - $this->email = strtolower($this->email); - ensure($this->email == $this->user->getEmail() || !userExists($this->email), "Un compte existe déjà avec cette adresse e-mail."); - $this->receive_animath_mails = $this->receive_animath_mails != false; - } - - public function updateAccount() - { - $this->user->setSurname($this->surname); - $this->user->setFirstName($this->first_name); - $this->user->setSchool($this->school); - $this->user->setCity($this->city); - $this->user->setCountry($this->country); - $this->user->setClass($this->class); - $this->user->setDescription($this->description); - $this->user->setReceiveAnimathMails($this->receive_animath_mails); - - if ($this->email != $this->user->getEmail()) { - $this->user->setEmail($this->email); - $this->user->setConfirmEmailToken(genRandomPhrase(64)); - - Mailer::sendChangeEmailAddressMail($this->user); - } - } -} - -class NewPassword -{ - private $user; - private $old_password; - private $new_password; - private $confirm_password; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - - $this->user = $_SESSION["user"]; - } - - public function makeVerifications() - { - ensure($this->user->checkPassword($this->old_password), "L'ancien mot de passe est incorrect."); - ensure(strlen($this->new_password) >= 8, "Le mot de passe doit comporter au moins 8 caractères."); - ensure($this->new_password == $this->confirm_password, "Les deux mots de passe sont différents."); - } - - public function updatePassword() - { - $this->user->setPassword($this->new_password); - - Mailer::sendChangePasswordMail($this->user); - } -} - -class SendDocument -{ - private $file; - - public function __construct() - { - $this->file = $_FILES["document"]; - } - - public function makeVerifications() - { - global $LOCAL_PATH; - - ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); - ensure(!$this->file["error"], "Une erreur est survenue."); - $mime_type = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]); - ensure($mime_type == "application/pdf" || $mime_type == "image/png" || $mime_type == "image/jpeg", "Le fichier doit être au format PDF."); - ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenu dans l'envoi du fichier. Veuillez vérifier que le fichier pèse moins de 2 Mo. Merci de compresser votre fichier si tel n'est pas le cas. En cas de problème, merci de contacter l'administrateur du serveur."); - } - - public function sendDocument() - { - global $LOCAL_PATH, $DB; - - do - $id = genRandomPhrase(64); - while (file_exists("$LOCAL_PATH/files/$id")); - - if (!rename($this->file["tmp_name"], "$LOCAL_PATH/files/$id")) - throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); - - $req = $DB->prepare("INSERT INTO `documents`(`file_id`, `user`, `team`, `problem`) - VALUES (?, ?, ?, ?);"); - $req->execute([$id, $_SESSION["user_id"], $_SESSION["team"]->getId(), $_SESSION["team"]->getProblem()]); - } -} - -$documents = $user->getAllDocuments(); - -require_once "server_files/views/mon_compte.php"; diff --git a/server_files/controllers/mon_equipe.php b/server_files/controllers/mon_equipe.php deleted file mode 100644 index cde263d..0000000 --- a/server_files/controllers/mon_equipe.php +++ /dev/null @@ -1,112 +0,0 @@ -makeVerifications(); - $my_team->updateTeam(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -/** - * @var User $user - * @var Team $team - */ -$user = $_SESSION["user"]; -$team = $user->getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - -if (isset($_POST["request_validation"])) { - if (!canValidate($team)) { - $has_error = true; - $error_message = "Votre équipe ne peut pas demander la validation : il manque soit des participants, soit des documents."; - } - else if (!isset($_POST["engage"])) { - $has_error = true; - $error_message = "Vous devez cocher la case qui vous engage à participer à l'intégralité des Correspondances."; - } - else { - $team->setValidationStatus(ValidationStatus::WAITING); - Mailer::sendRequestValidationMail($team); - } -} - -/** @var Question[][] $questions_received */ -$questions_received = []; - -if (isset($_SESSION["user_id"]) && isset($_SESSION["teams"]) && sizeof($_SESSION["teams"]) > 0) { - if ($team == null) - require_once "server_files/404.php"; - - if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId()) - require_once "server_files/403.php"; - - $documents = $team->getAllDocuments(); -} -else - require_once "server_files/403.php"; - -if (isset($_GET["publish_videos"])) { - $team->setAllowPublish(!$team->allowPublish()); - header("Location: /mon-equipe"); - exit(); -} - -class MyTeam -{ - public $name; - public $trigram; - public $problem; - /** @var Team */ - private $team; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = htmlspecialchars($value); - - $this->trigram = strtoupper($this->trigram); - $this->team = $_SESSION["team"]; - } - - public function makeVerifications() - { - global $CONFIG; - - ensure($this->name != "" && $this->name != null, "Veuillez spécifier un nom d'équipe."); - ensure($this->name == $this->team->getName() || !teamExists($this->name), "Une équipe existe déjà avec ce nom."); - ensure(preg_match("#^[\p{L} ]+$#ui", $this->name), "Le nom de l'équipe ne doit pas comporter de caractères spéciaux."); - ensure(preg_match("#^[A-Z]{3}$#", $this->trigram), "Le trigramme n'est pas valide."); - ensure($this->trigram == $this->team->getTrigram() || !trigramExists($this->trigram), "Une équipe a déjà choisi ce trigramme."); - ensure(preg_match("#^[0-4]$#", $this->problem), "Le problème indiqué n'existe pas."); - ensure(date("Y-m-d H:i:s") <= $CONFIG->getInscriptionDate(), "Les inscriptions sont terminées."); - ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Votre équipe est déjà validée ou en cours de validation."); - } - - public function updateTeam() - { - global $DB, $URL_BASE; - - $this->team->setName($this->name); - $this->team->setTrigram($this->trigram); - $this->team->setProblem($this->problem); - - $DB->exec("UPDATE `teams` SET `problem` = " . $this->problem . " WHERE `id` = " . $this->team->getId() . ";"); - $DB->exec("UPDATE `documents` SET `problem` = " . $this->problem . " WHERE `team` = " . $this->team->getId() . ";"); - - header("Location: $URL_BASE/mon-equipe"); - } -} - -require_once "server_files/views/mon_equipe.php"; diff --git a/server_files/controllers/poser_questions.php b/server_files/controllers/poser_questions.php deleted file mode 100644 index 7aa3ee8..0000000 --- a/server_files/controllers/poser_questions.php +++ /dev/null @@ -1,137 +0,0 @@ -getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - -if ($team == null) - require_once "server_files/404.php"; - -if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId() || $team->getValidationStatus() != ValidationStatus::VALIDATED) - require_once "server_files/403.php"; - -$has_error = false; -$error_message = null; - -if (isset($_POST["give_questions"])) { - $give_questions = new GiveQuestions($_POST, $_FILES); - try { - $give_questions->makeVerifications(); - $give_questions->giveQuestions(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class GiveQuestions -{ - private $to; - /** - * @var Team $to_team - */ - private $to_team; - private $question_0; - private $question_1; - private $question_2; - private $question_3; - private $question_4; - private $question_5; - private $question_6; - private $questions; - private $no_drawing; - private $has_files; - private $files; - - public function __construct($data, $files) - { - foreach ($data as $key => $value) { - $this->$key = $value; - } - - $this->files = []; - $this->has_files = false; - - for ($i = 0; $i <= 6; ++$i) { - if (strlen($files["file_$i"]["name"]) > 0) { - $this->files[] = $files["file_$i"]; - $this->has_files = true; - } - else - $this->files[] = null; - } - - $this->questions = [$this->question_0, $this->question_1, $this->question_2, $this->question_3, $this->question_4, $this->question_5, $this->question_6]; - } - - public function makeVerifications() - { - global $LOCAL_PATH, $team; - - $this->to_team = Team::fromTrigram($this->to); - ensure($this->to_team, "L'équipe indiquée n'existe pas."); - ensure($team->getProblem() == $this->to_team->getProblem(), "Les équipes ne travaillent pas sur le même problème."); - ensure($this->question_1 != null && $this->question_1 != "" && $this->question_2 != null && $this->question_2 != "" && $this->question_3 != null && $this->question_3 != "", - "Vous devez poser au moins 3 questions."); - ensure(!$this->has_files || $this->no_drawing, "Vous devez confirmer ne pas avoir inclus de texte dans vos pièces jointes."); - - for ($i = 4; $i <= 6; ++$i) { - if ($this->questions[$i] == "") - $this->questions[$i] = null; - } - - for ($i = 0; $i <= 6; ++$i) { - ensure($this->files[$i]["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); - ensure(!$this->files[$i]["error"], "Une erreur est survenue. Veuillez vérifier vos pièces jointes. Elles ne doivent pas peser plus de 2 Mo chacune."); - } - - ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenue dans l'envoi du fichier. Veuillez contacter l'administrateur du serveur."); - } - - public function giveQuestions() - { - global $LOCAL_PATH, $team; - - /** @var Question[] $questions */ - $questions = Question::getQuestions($team, $this->to_team); - for ($i = 0; $i <= 6; ++$i) { - $question = $questions[$i]; - if ($question->getQuestion() != $this->questions[$i] && $question->getAttachedFile() != null) { - unlink("$LOCAL_PATH/files/" . $question->getAttachedFile()); - $question->setAttachedFile(null); - } - - $question->setQuestion($this->questions[$i]); - - if ($this->files[$i] != null) { - do - $file_id = genRandomPhrase(64); - while (file_exists("$LOCAL_PATH/files/$file_id")); - - if (!rename($this->files[$i]["tmp_name"], "$LOCAL_PATH/files/$file_id")) - throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); - - $question->setAttachedFile($file_id); - } - } - } -} - -/** - * @var Team[] $receivers - * @var Video[] $videos - * @var Question[][] $questions - */ -$receivers = [Team::fromId($team->getVideoTeamIds()[0]), Team::fromId($team->getVideoTeamIds()[1])]; -$videos = [Video::getVideo(Reason::SOLUTION, $receivers[0], Video::ACCEPTED), - Video::getVideo(Reason::SOLUTION, $receivers[1], Video::ACCEPTED)]; -$questions = [Question::getQuestions($team, $receivers[0]), - Question::getQuestions($team, $receivers[1])]; - -require_once "server_files/views/poser_questions.php"; \ No newline at end of file diff --git a/server_files/controllers/probleme.php b/server_files/controllers/probleme.php deleted file mode 100644 index 59130b8..0000000 --- a/server_files/controllers/probleme.php +++ /dev/null @@ -1,26 +0,0 @@ -getValidationStatus() == ValidationStatus::VALIDATED) - $validated_emails = array_merge($validated_emails, $team->getAllEmails()); - else - $not_validated_emails = array_merge($not_validated_emails, $team->getAllEmails()); -} - -require_once "server_files/views/probleme.php"; diff --git a/server_files/controllers/profiles.php b/server_files/controllers/profiles.php deleted file mode 100644 index cf4d789..0000000 --- a/server_files/controllers/profiles.php +++ /dev/null @@ -1,9 +0,0 @@ -makeVerifications(); - $join_team->joinTeam(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class JoinTeam -{ - private $access_code; - private $team; - private $min_null_index; - - public function __construct($data) - { - $this->access_code = strtolower(htmlspecialchars($data["access_code"])); - $this->team = Team::fromAccessCode($this->access_code); - } - - public function makeVerifications() - { - global $CONFIG; - - ensure(date("Y-m-d H:i:s") < $CONFIG->getInscriptionDate(), "La date limite d'inscription est dépassée."); - ensure($_SESSION["team"] == null || $_SESSION["role"] == Role::ENCADRANT, "Vous êtes déjà dans une équipe."); - ensure(preg_match("#[a-z0-9]{6}#", $this->access_code), "Le code d'accès doit comporter 6 caractères alphanumériques."); - ensure($this->team != null, "Ce code d'accès est invalide."); - ensure($this->team->getValidationStatus() == ValidationStatus::NOT_READY, "Cette équipe est déjà validée ou en cours de validation, vous ne pouvez pas la rejoindre."); - - for ($i = 1; $i <= ($_SESSION["role"] == Role::PARTICIPANT ? 5 : 1); ++$i) { - if (($_SESSION["role"] == Role::PARTICIPANT ? $this->team->getParticipants()[$i - 1] : $this->team->getEncadrantId()) == NULL) - break; - } - - $this->min_null_index = $i; - - ensure($_SESSION["role"] == Role::PARTICIPANT && $this->min_null_index <= 5 || $_SESSION["role"] == Role::ENCADRANT && $this->min_null_index <= 1, "Il n'y a plus de place pour vous dans l'équipe."); - } - - public function joinTeam() - { - global $team; - - $user = $_SESSION["user"]; - - $user->setTeamId($this->team->getId()); - - if ($_SESSION["role"] == Role::ENCADRANT) - $this->team->setEncadrant($user->getId()); - else - $this->team->setParticipant($this->min_null_index, $user->getId()); - - $team = $_SESSION["team"] = $this->team; - - Mailer::sendJoinTeamMail($user, $this->team); - } -} - -require_once "server_files/views/rejoindre_equipe.php"; diff --git a/server_files/controllers/repondre_questions.php b/server_files/controllers/repondre_questions.php deleted file mode 100644 index 924171b..0000000 --- a/server_files/controllers/repondre_questions.php +++ /dev/null @@ -1,126 +0,0 @@ -getRole() == Role::PARTICIPANT ? $_SESSION["team"] : Team::fromTrigram($_GET["trigram"]); - -if ($team == null) - require_once "server_files/404.php"; - -if ($user->getRole() == Role::ENCADRANT && $team->getEncadrantId() != $user->getId() || $team->getValidationStatus() != ValidationStatus::VALIDATED) - require_once "server_files/403.php"; - -$has_error = false; -$error_message = null; - -if (isset($_POST["answer"])) { - $answer_questions = new AnswerQuestions($_POST, $_FILES); - try { - $answer_questions->makeVerifications(); - $answer_questions->answerQuestions(); - } catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class AnswerQuestions -{ - private $from; - /** - * @var Team $to_team - */ - private $from_team; - private $answer_0; - private $answer_1; - private $answer_2; - private $answer_3; - private $answer_4; - private $answer_5; - private $answer_6; - private $answers; - private $no_drawing; - private $has_files; - private $files; - - public function __construct($data, $files) - { - foreach ($data as $key => $value) { - $this->$key = $value; - } - - $this->files = []; - $this->has_files = false; - - for ($i = 0; $i <= 6; ++$i) { - if (strlen($files["file_$i"]["name"]) > 0) { - $this->files[] = $files["file_$i"]; - $this->has_files = true; - } - else - $this->files[] = null; - } - - $this->answers = [$this->answer_0, $this->answer_1, $this->answer_2, $this->answer_3, $this->answer_4, $this->answer_5, $this->answer_6]; - } - - public function makeVerifications() - { - global $LOCAL_PATH, $team; - - $this->from_team = Team::fromTrigram($this->from); - ensure($this->from_team != null, "L'équipe indiquée n'existe pas."); - ensure($team->getProblem() == $this->from_team->getProblem(), "Les équipes ne travaillent pas sur le même problème."); - ensure(!$this->has_files || $this->no_drawing, "Vous devez confirmer ne pas avoir inclus de texte dans vos pièces jointes."); - - for ($i = 1; $i <= 6; ++$i) { - if ($this->answers[$i] == "") - $this->answers[$i] = null; - } - - for ($i = 0; $i <= 6; ++$i) { - ensure($this->files[$i]["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); - ensure(!$this->files[$i]["error"], "Une erreur est survenue. Veuillez vérifier vos pièces jointes. Elles ne doivent pas peser plus de 2 Mo chacune."); - } - - ensure(is_dir("$LOCAL_PATH/files") || mkdir("$LOCAL_PATH/files"), "Un problème est survenue dans l'envoi du fichier. Veuillez contacter l'administrateur du serveur."); - } - - public function answerQuestions() - { - global $LOCAL_PATH, $team; - - /** @var Question[] $questions */ - $questions = Question::getQuestions($this->from_team, $team); - for ($i = 0; $i <= 6; ++$i) { - $question = $questions[$i]; - if ($question->getAnswer() != $this->answers[$i] && $question->getAttachedFileAnswer() != null) { - unlink("$LOCAL_PATH/files/" . $question->getAttachedFileAnswer()); - $question->setAttachedFileAnswer(null); - } - - $question->setAnswer($this->answers[$i]); - - if ($this->files[$i] != null) { - do - $file_id = genRandomPhrase(64); - while (file_exists("$LOCAL_PATH/files/$file_id")); - - if (!rename($this->files[$i]["tmp_name"], "$LOCAL_PATH/files/$file_id")) - throw new AssertionError("Une erreur est survenue lors de l'envoi du fichier."); - - $question->setAttachedFileAnswer($file_id); - } - } - } -} - -$questions = Question::getQuestionsTo($team); -$video = Video::getVideo(Reason::SOLUTION, $team); - -require_once "server_files/views/repondre_questions.php"; \ No newline at end of file diff --git a/server_files/controllers/suivi_correspondances.php b/server_files/controllers/suivi_correspondances.php deleted file mode 100644 index 522fabd..0000000 --- a/server_files/controllers/suivi_correspondances.php +++ /dev/null @@ -1,141 +0,0 @@ -makeVerifications(); - $validate_video->validate(); - } - catch (AssertionError $e) { - $has_error = true; - $error_message = $e->getMessage(); - } -} - -class ValidateVideo -{ - private $video_id; - private $accept; - private $reject; - /** @var Video */ - private $video; - private $message; - - public function __construct($data) - { - foreach ($data as $key => $value) - $this->$key = $value; - } - - public function makeVerifications() - { - $this->video = Video::fromId($this->video_id); - ensure($this->video != null, "La vidéo n'existe pas."); - ensure($this->video->getValidation() != 1, "La vidéo est déjà validée / rejetée."); - ensure(($this->accept == null || $this->reject == null) && $this->accept != $this->reject, "Impossible de déterminer s'il faut accepter ou non la vidéo."); - } - - public function validate() - { - $this->video->setValidation($this->accept ? 1 : -1); - Mailer::validateVideo($this->video, $this->message); - } -} - -$videos = []; - -if (!isset($_GET["problem"])) { - for ($problem = 1; $problem <= 4; ++$problem) - $videos[] = Video::getVideos(Reason::SOLUTION, $problem); -} -else { - $videos = [[], [], [], []]; - $videos[intval($_GET["problem"]) - 1] = Video::getVideos(Reason::SOLUTION, intval($_GET["problem"])); -} - -$waiting_teams = []; -$waiting_emails = []; - -switch (Phase::getCurrentPhase()) { - case Phase::PHASE1: - case Phase::PHASE12: - $req = $DB->query("SELECT DISTINCT `teams`.`id`, `teams`.`problem`, `teams`.`trigram` FROM `teams` WHERE `validation_status` = '" . ValidationStatus::getName(ValidationStatus::VALIDATED) . "'" - . " AND `id` NOT IN (SELECT DISTINCT `team` FROM `videos` WHERE `reason` = 'SOLUTION' AND `validation` = " . Video::ACCEPTED . ")" - . " AND `year` = $YEAR ORDER BY `problem`, `trigram`;"); - break; - case Phase::PHASE2: - case Phase::PHASE23: - $req = $DB->query("SELECT DISTINCT `teams`.`id`, `teams`.`problem`, `teams`.`trigram` FROM `teams`" - . " WHERE `id` NOT IN (SELECT `q1`.`from` FROM `questions` AS `q1`" - . " JOIN `questions` AS `q2` ON `q2`.`from` = `q1`.`from` AND `q2`.`number` = 2" - . " JOIN `questions` AS `q3` ON `q3`.`from` = `q1`.`from` AND `q3`.`number` = 3" - . " JOIN `questions` AS `q4` ON `q4`.`from` = `q1`.`from` AND `q4`.`number` = 4" - . " JOIN `questions` AS `q5` ON `q5`.`from` = `q1`.`from` AND `q5`.`number` = 5" - . " JOIN `questions` AS `q6` ON `q6`.`from` = `q1`.`from` AND `q6`.`number` = 6" - . " WHERE `q1`.`number` = 1" - . " AND (`q1`.`question` != '" . Question::DEFAULT_QUESTIONS[0] . "'" - . " OR `q2`.`question` != '" . Question::DEFAULT_QUESTIONS[1] . "'" - . " OR `q3`.`question` != '" . Question::DEFAULT_QUESTIONS[2] . "'" - . " OR `q4`.`question` IS NOT NULL" - . " OR `q5`.`question` IS NOT NULL" - . " OR `q6`.`question` IS NOT NULL))" - . " AND `validation_status` = '" . ValidationStatus::getName(ValidationStatus::VALIDATED) . "'" - . " AND `year` = $YEAR ORDER BY `problem`, `trigram`;"); - break; - case Phase::PHASE3: - case Phase::PHASE34: - $req = $DB->query("SELECT DISTINCT `teams`.`id`, `teams`.`problem`, `teams`.`trigram` FROM `teams`" - . " WHERE `id` NOT IN (SELECT `q1`.`to` FROM `questions` AS `q1`" - . " JOIN `questions` AS `q2` ON `q2`.`to` = `q1`.`to` AND `q2`.`number` = 2" - . " JOIN `questions` AS `q3` ON `q3`.`to` = `q1`.`to` AND `q3`.`number` = 3" - . " JOIN `questions` AS `q4` ON `q4`.`to` = `q1`.`to` AND `q4`.`number` = 4" - . " JOIN `questions` AS `q5` ON `q5`.`to` = `q1`.`to` AND `q5`.`number` = 5" - . " JOIN `questions` AS `q6` ON `q6`.`to` = `q1`.`to` AND `q6`.`number` = 6" - . " WHERE `q1`.`number` = 1" - . " AND (`q1`.`answer` IS NOT NULL" - . " OR `q2`.`answer` IS NOT NULL" - . " OR `q3`.`answer` IS NOT NULL" - . " OR `q4`.`answer` IS NOT NULL" - . " OR `q5`.`answer` IS NOT NULL" - . " OR `q6`.`answer` IS NOT NULL))" - . " AND `validation_status` = '" . ValidationStatus::getName(ValidationStatus::VALIDATED) . "'" - . " AND `year` = $YEAR ORDER BY `problem`, `trigram`;"); - break; - case Phase::PHASE4: - case Phase::END: - $req = $DB->query("SELECT DISTINCT `teams`.`id`, `teams`.`problem`, `teams`.`trigram` FROM `teams` WHERE `validation_status` = '" . ValidationStatus::getName(ValidationStatus::VALIDATED) . "'" - . " AND (`id` NOT IN (SELECT DISTINCT `team` FROM `videos` WHERE `reason` = 'ANSWER1' AND `validation` = " . Video::ACCEPTED . ")" - . " OR `id` NOT IN (SELECT DISTINCT `team` FROM `videos` WHERE `reason` = 'ANSWER2' AND `validation` = " . Video::ACCEPTED . "))" - . " AND `year` = $YEAR ORDER BY `problem`, `trigram`;"); - break; -} - -if (isset($req)) { - $waiting_emails = []; - while (($data = $req->fetch()) !== false) { - $team = Team::fromId($data["id"]); - if (Phase::getCurrentPhase() >= Phase::PHASE12 && $team->getSolution() == null) - continue; - if (isset($_GET["problem"]) && intval($_GET["problem"]) != $team->getProblem()) - continue; - $waiting_teams[] = $team; - $waiting_emails = array_merge($waiting_emails, $team->getAllEmails()); - } -} - -$all_emails = []; -foreach (Team::getAllTeams() as $team) { - if (Phase::getCurrentPhase() >= Phase::PHASE12 && $team->getSolution() == null) - continue; - if (isset($_GET["problem"]) && intval($_GET["problem"]) != $team->getProblem()) - continue; - $all_emails = array_merge($all_emails, $team->getAllEmails()); -} - -require_once "server_files/views/suivi_correspondances.php"; \ No newline at end of file diff --git a/server_files/controllers/view_file.php b/server_files/controllers/view_file.php deleted file mode 100644 index f54e827..0000000 --- a/server_files/controllers/view_file.php +++ /dev/null @@ -1,51 +0,0 @@ -getTeamId());; - $trigram = $team->getTrigram(); - - $user = User::fromId($file->getUserId()); - - if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT) && $user->getId() != $_SESSION["user_id"]) - require_once "server_files/403.php"; - - $surname = $user->getSurname(); - $first_name = $user->getFirstName(); - $mime_type = finfo_file(finfo_open(FILEINFO_MIME_TYPE), "$LOCAL_PATH/files/$id"); - $ext = $mime_type == "application/pdf" ? "pdf" : ($mime_type == "image/png" ? "png" : "jpg"); - $name = "Autorisation de droit à l'image de $first_name $surname.$ext"; - - header("Content-Type: " . $mime_type); -} -else { - $question = Question::fromAttachedFile($id); - if ($question != null) - { - $from = Team::fromId($question->getFrom()); - $to = Team::fromId($question->getTo()); - $mime_type = finfo_file(finfo_open(FILEINFO_MIME_TYPE), "$LOCAL_PATH/files/$id"); - $name = "Pièce jointe n°" . $question->getNumber() . " de l'équipe " . $from->getTrigram() . " pour l'équipe " . $from->getTrigram() . " (problème " . $question->getProblem() . ")"; - $name .= getExtFromMimeType($mime_type); - header("Content-Type: " . $mime_type); - } - else - require_once "server_files/404.php"; -} - -header("Content-Disposition: inline; filename=\"$name\""); - -readfile("$LOCAL_PATH/files/$id"); - -exit(); \ No newline at end of file diff --git a/server_files/model.php b/server_files/model.php deleted file mode 100644 index aa4fb2d..0000000 --- a/server_files/model.php +++ /dev/null @@ -1,326 +0,0 @@ -getRole(); - - $_SESSION["teams"] = $user->getTeams(); - - if ($user->getRole() == Role::PARTICIPANT) - $_SESSION["team"] = sizeof($_SESSION["teams"]) > 0 ? $_SESSION["teams"][0] : null; - } - - if (isset($_GET["view-as-admin"])) { - if (isset($_SESSION["admin"])) { - $_SESSION["user_id"] = $_SESSION["admin"]; - unset($_SESSION["admin"]); - } - header("Location: /"); - exit(); - } -} - -function quitTeam($user_id = -1) -{ - global $DB, $URL_BASE; - - if ($user_id == -1) - header("Location: $URL_BASE"); - - $user_id = $user_id >= 0 ? $user_id : $_SESSION["user_id"]; - /** @var User $user */ - $user = User::fromId($user_id); - $role = $user->getRole(); - - if ($role == Role::ADMIN) - return; - - if ($role == Role::PARTICIPANT) - for ($i = 1; $i <= 5; ++$i) - /** @noinspection SqlResolve */ - $DB->exec("UPDATE `teams` SET `participant_$i` = NULL WHERE `participant_$i` = $user_id;"); - else - $DB->exec("UPDATE `teams` SET `encadrant` = NULL WHERE `encadrant` = $user_id;"); - $user->setTeamId(null); - for ($i = 1; $i <= 4; ++$i) { - /** @noinspection SqlResolve */ - $DB->exec("UPDATE `teams` SET `participant_$i` = `participant_" . strval($i + 1) . "`, `participant_" . strval($i + 1) . "` = NULL WHERE `participant_$i` IS NULL;"); - } - - $DB->exec("DELETE FROM `teams` WHERE `encadrant` IS NULL AND `participant_1` IS NULL;"); - $req = $DB->query("SELECT `file_id` FROM `documents` WHERE `user` = $user_id;"); - while (($data = $req->fetch()) !== false) - unlink("$URL_BASE/files/" . $data["file_id"]); - $DB->exec("DELETE FROM `documents` WHERE `user` = $user_id;"); - - $_SESSION["team"] = null; - unset($_SESSION["team"]); - - $_SESSION["teams"] = $user->getTeams(); -} - -function userExists($email) -{ - global $DB, $YEAR; - - $req = $DB->prepare("SELECT `id` FROM `users` WHERE `email` = ? AND `year` = '$YEAR';"); - $req->execute([$email]); - return $req->fetch(); -} - -function teamExists($name) -{ - global $DB, $YEAR; - - $req = $DB->prepare("SELECT `id` FROM `teams` WHERE `name` = ? AND `year` = '$YEAR';"); - $req->execute([$name]); - return $req->fetch(); -} - -function trigramExists($trigram) -{ - global $DB, $YEAR; - - $req = $DB->prepare("SELECT `id` FROM `teams` WHERE `trigram` = ? AND `year` = '$YEAR';"); - $req->execute([$trigram]); - return $req->fetch(); -} - -function canValidate(Team $team) -{ - global $DB, $CONFIG; - - $can_validate = date("Y-m-d H:i:s") < $CONFIG->getInscriptionDate(); - $can_validate &= $team->getValidationStatus() == ValidationStatus::NOT_READY; - $can_validate &= $team->getEncadrantId() != null; - $can_validate &= $team->getParticipants()[2] != null; - $can_validate &= preg_match("#[1-4]#", $team->getProblem()); - - for ($i = 0; $i < 5; ++$i) { - if ($team->getParticipants()[$i] === NULL) - continue; - - $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `problem` = ?;"); - $req->execute([$team->getParticipants()[$i], $team->getProblem()]); - $d = $req->fetch(); - $can_validate &= $d["version"] > 0; - } - - return $can_validate; -} - -function printDocuments($documents) -{ - if (sizeof($documents) == 0) { - echo "
\nPas de document envoyé pour le moment.\n
\n"; - return; - } - - echo "
\n"; - foreach ($documents as $document) { - $file_id = $document->getFileId(); - $user = User::fromId($document->getUserId()); - $surname = $user->getSurname(); - $first_name = $user->getFirstName(); - $name = "Autorisation de droit à l'image"; - $version = $document->getVersion(); - echo "$name de $first_name $surname (version $version) : Télécharger
\n"; - } - echo "
\n"; -} - -function getZipFile($problem, $team_id = -1) -{ - global $LOCAL_PATH; - - $zip = new ZipArchive(); - - $file_name = tempnam("tmp", "corres2math-"); - - if ($zip->open($file_name, ZipArchive::CREATE) !== true) { - die("Impossible de créer le fichier zip."); - } - - $data = Document::getAllDocuments($problem, $team_id); - - /** @var Document $file */ - foreach ($data as $file) { - $file_id = $file->getFileId(); - $user = User::fromId($file->getUserId()); - $mime_type = finfo_file(finfo_open(FILEINFO_MIME_TYPE), "$LOCAL_PATH/files/$file_id"); - $ext = $mime_type == "application/pdf" ? "pdf" : ($mime_type == "image/png" ? "png" : "jpg"); - $name = "Autorisation de droit à l'image de " . $user->getFirstName() . " " . $user->getSurname() . "." . $ext; - - $zip->addFile("$LOCAL_PATH/files/$file_id", $name); - } - - $zip->close(); - - return $file_name; -} - -function exportUserData() { - global $DB, $YEAR; - - $file_name = tempnam("tmp", "corres2math-"); - - $csv = "Identifiant,Nom,Prénom,E-mail,École,Ville,Pays,Classe,Description,Rôle,Équipe,Autorise l'envoi de mails,Date d'inscription\n"; - - $req = $DB->query("SELECT `id` FROM `users` WHERE `year` = $YEAR;"); - while (($data = $req->fetch()) !== false) { - $user = User::fromId($data["id"]); - - $csv .= $user->getId() . ","; - $csv .= $user->getSurname() . ","; - $csv .= $user->getFirstName() . ","; - $csv .= $user->getEmail() . ","; - $csv .= $user->getSchool() . ","; - $csv .= $user->getCity() . ","; - $csv .= $user->getCountry() . ","; - $csv .= SchoolClass::getTranslatedName($user->getClass()) . ","; - $csv .= $user->getDescription() . ","; - $csv .= Role::getTranslatedName($user->getRole()) . ","; - $csv .= ($user->getTeamId() == null ? "" : Team::fromId($user->getTeamId())->getTrigram()) . ","; - $csv .= ($user->doReceiveAnimathMails() ? "oui" : "non") . ","; - $csv .= $user->getInscriptionDate() . "\n"; - } - file_put_contents($file_name, $csv, FILE_APPEND); - - return $file_name; -} - -function exportTeamData() { - global $DB, $YEAR; - - $file_name = tempnam("tmp", "corres2math-"); - - $csv = "Identifiant,Nom,Trigramme,Problème,Encadrant,Participant 1,Participant 2,Participant 3,Participant 4,Participant 5," - . "Date d'inscription,Autorise la publication,État de validation,Code d'accès\n"; - - $req = $DB->query("SELECT `id` FROM `teams` WHERE `year` = $YEAR ORDER BY `problem`;"); - while (($data = $req->fetch()) !== false) { - $team = Team::fromId($data["id"]); - - $csv .= $team->getId() . ","; - $csv .= $team->getName() . ","; - $csv .= $team->getTrigram() . ","; - $csv .= $team->getProblem() . ","; - $csv .= $team->getEncadrantId() . ","; - $csv .= $team->getParticipants()[0] . ","; - $csv .= $team->getParticipants()[1] . ","; - $csv .= $team->getParticipants()[2] . ","; - $csv .= $team->getParticipants()[3] . ","; - $csv .= $team->getParticipants()[4] . ","; - $csv .= $team->getInscriptionDate() . ","; - $csv .= $team->allowPublish() . ","; - $csv .= ValidationStatus::getTranslatedName($team->getValidationStatus()) . ","; - $csv .= $team->getAccessCode() . "\n"; - } - file_put_contents($file_name, $csv, FILE_APPEND); - - return $file_name; -} - -function exportProblemsData() { - global $DB, $URL_BASE, $YEAR; - - $file_name = tempnam("tmp", "corres2math-"); - - $csv = "Équipe,Problème,Lien,Équipe 1 ayant reçu la vidéo," - . "Question 1,Pièce jointe,Réponse,Pièce jointe," - . "Question 2,Pièce jointe,Réponse,Pièce jointe," - . "Question 3,Pièce jointe,Réponse,Pièce jointe," - . "Question 4,Pièce jointe,Réponse,Pièce jointe," - . "Question 5,Pièce jointe,Réponse,Pièce jointe," - . "Question 6,Pièce jointe,Réponse,Pièce jointe," - . "Vidéo de réponse," - . "Équipe 2 ayant reçu la vidéo," - . "Question 1,Pièce jointe,Réponse,Pièce jointe," - . "Question 2,Pièce jointe,Réponse,Pièce jointe," - . "Question 3,Pièce jointe,Réponse,Pièce jointe," - . "Question 4,Pièce jointe,Réponse,Pièce jointe," - . "Question 5,Pièce jointe,Réponse,Pièce jointe," - . "Question 6,Pièce jointe,Réponse,Pièce jointe," - . "Vidéo de réponse\n"; - - $req = $DB->query("SELECT `id` FROM `teams` WHERE `validation_status` = 'VALIDATED' AND `year` = $YEAR ORDER BY `problem`;"); - while (($data = $req->fetch()) !== false) { - $team = Team::fromId($data["id"]); - $video = Video::getVideo(Reason::SOLUTION, $team); - $questions_received = Question::getQuestionsTo($team); - - $csv .= $team->getTrigram() . ","; - $csv .= $team->getProblem() . ","; - $csv .= ($video == null ? "" : $video->getLink()) . ","; - for ($i = 0; $i < 2; ++$i) { - /** @var Question[] $questions */ - $questions = $questions_received[$i]; - $asker = Team::fromId($questions[0]->getFrom()); - $csv .= $asker->getTrigram() . ","; - - for ($j = 0; $j < 6; ++$j) { - $question = $questions[$j]; - - if ($question == null) { - $csv .= ",,,,"; - continue; - } - - $csv .= $question->getQuestion() . ","; - $csv .= ($question->getAttachedFile() == null ? "" : $URL_BASE . "/file/" . $question->getAttachedFile()) . ','; - $csv .= $question->getAnswer() . ","; - $csv .= ($question->getAttachedFileAnswer() == null ? "" : $URL_BASE . "/file/" . $question->getAttachedFileAnswer()) . ','; - } - - $answer = Video::getVideo($asker->getVideoTeamIds()[0] == $team->getId() ? Reason::ANSWER1 : Reason::ANSWER2, - $asker, Video::ACCEPTED); - $csv .= $answer == null ? "" : $answer->getLink(); - $csv .= ($i == 0 ? "," : "\n"); - } - } - file_put_contents($file_name, $csv, FILE_APPEND); - - return $file_name; -} - -function displayVideo($link) -{ - if (preg_match("#(https?://|)(www\.|)(youtube\.com/watch\?v=|youtu.be/)([a-zA-Z0-9,\-,_]*)?.*?#", $link, $matches)) { - $code = $matches[4]; - /** @noinspection HtmlDeprecatedAttribute */ - /** @noinspection HtmlDeprecatedTag */ - echo "

\n"; - } - elseif (preg_match("#(https?://|)drive\.google\.com/(file/d/|open\?id=)([a-zA-Z0-9\-_]*)/?.*?#", $link, $matches)) { - $code = $matches[3]; - /** @noinspection HtmlDeprecatedAttribute */ - /** @noinspection HtmlDeprecatedTag */ - echo "

\n"; - } - elseif (preg_match("#(https?://|)(www\.|)vimeo\.com/([0-9]*)#", $link, $matches)) { - $code = $matches[3]; - /** @noinspection HtmlDeprecatedAttribute */ - /** @noinspection HtmlDeprecatedTag */ - echo "
"; - - } - elseif (preg_match("#(https?://|)(www\.|)dailymotion\.com/video/(.*)#", $link, $matches)) { - $code = $matches[3]; - /** @noinspection HtmlDeprecatedAttribute */ - /** @noinspection HtmlDeprecatedTag */ - echo "
"; - } -} \ No newline at end of file diff --git a/server_files/services/mail.php b/server_files/services/mail.php deleted file mode 100644 index f3963eb..0000000 --- a/server_files/services/mail.php +++ /dev/null @@ -1,256 +0,0 @@ -\r\n"; - $headers .= "Reply-To: \"Contact corres2Math\" \r\n"; - $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; - - ensure(mail($email, $subject, $content, $headers), "Un problème est survenu dans l'envoi d'un mail. Veuiller contacter votre administrateur."); - } - - private static function broadcastToTeam(Team $team, $subject, $content, $from = "contact") - { - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - - $encadrant = User::fromId($team->getEncadrantId()); - - if ($encadrant != null) { - $c = preg_replace("#{FIRST_NAME}#", $encadrant->getFirstName(), $content); - $c = preg_replace("#{SURNAME}#", $encadrant->getSurname(), $c); - self::sendMail($encadrant->getEmail(), $subject, $c, $from); - } - - foreach ($team->getParticipants() as $participant_id) { - $participant = User::fromId($participant_id); - if ($participant == null) - continue; - - $c = preg_replace("#{FIRST_NAME}#", $participant->getFirstName(), $content); - $c = preg_replace("#{SURNAME}#", $participant->getSurname(), $c); - self::sendMail($participant->getEmail(), $subject, $c, $from); - } - } - - private static function broadcastToAdmins($subject, $content, $from = "contact") - { - /** @var User $admin */ - foreach (User::getAdmins() as $admin) { - if (!$admin->doReceiveAnimathMails()) - continue; - - $c = preg_replace("#{FIRST_NAME}#", $admin->getFirstName(), $content); - $c = preg_replace("#{SURNAME}#", $admin->getSurname(), $c); - self::sendMail($admin->getEmail(), $subject, $c, $from); - } - } - - private static function getTemplate($name) - { - global $LOCAL_PATH; - return file_get_contents("$LOCAL_PATH/server_files/services/mail_templates/$name.html"); - } - - public static function sendRegisterMail(NewUser $new_user) - { - global $YEAR; - - $content = self::getTemplate("register"); - $content = preg_replace("#{FIRST_NAME}#", $new_user->first_name, $content); - $content = preg_replace("#{SURNAME}#", $new_user->surname, $content); - $content = preg_replace("#{TOKEN}#", $new_user->confirm_email_token, $content); - - self::sendMail($new_user->email, "Inscription aux Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendConfirmEmail(User $user) - { - global $YEAR; - - $content = self::getTemplate("confirm_email"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - $content = preg_replace("#{TOKEN}#", $user->getConfirmEmailToken(), $content); - - self::sendMail($user->getEmail(), "Confirmation d'adresse e-mail – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendChangeEmailAddressMail(User $user) - { - global $YEAR; - - $content = self::getTemplate("change_email_address"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - $content = preg_replace("#{TOKEN}#", $user->getConfirmEmailToken(), $content); - - self::sendMail($user->getEmail(), "Changement d'adresse e-mail – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendForgottenPasswordProcedureMail(User $user) - { - global $YEAR; - - $content = self::getTemplate("forgotten_password"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - $content = preg_replace("#{TOKEN}#", $user->getForgottenPasswordToken(), $content); - - self::sendMail($user->getEmail(), "Mot de passe oublié – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendChangePasswordMail(User $user) - { - global $YEAR; - - $content = self::getTemplate("change_password"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - - self::sendMail($user->getEmail(), "Mot de passe changé – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendAddAdminMail(NewAdmin $new_admin) - { - global $YEAR; - - $content = self::getTemplate("add_admin"); - $content = preg_replace("#{FIRST_NAME}#", $new_admin->first_name, $content); - $content = preg_replace("#{SURNAME}#", $new_admin->surname, $content); - $content = preg_replace("#{PASSWORD}#", $new_admin->password, $content); - - self::sendMail($new_admin->email, "Ajout d'un administrateur – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendAddTeamMail(User $user, Team $team) - { - global $YEAR; - - $content = self::getTemplate("add_team"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - $content = preg_replace("#{ACCESS_CODE}#", $team->getAccessCode(), $content); - if ($team->getProblem() > 0) - $content = preg_replace("#{PROBLEM}#", "pour le problème" . $team->getProblem(), $content); - else - $content = preg_replace("#{PROBLEM}#", "", $content); - - self::sendMail($user->getEmail(), "Ajout d'une équipe – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendJoinTeamMail(User $user, Team $team) - { - global $YEAR; - - $content = self::getTemplate("join_team"); - $content = preg_replace("#{FIRST_NAME}#", $user->getFirstName(), $content); - $content = preg_replace("#{SURNAME}#", $user->getSurname(), $content); - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - if ($team->getProblem() > 0) - $content = preg_replace("#{PROBLEM}#", "pour le problème" . $team->getProblem(), $content); - else - $content = preg_replace("#{PROBLEM}#", "", $content); - - self::sendMail($user->getEmail(), "Équipe rejointe – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendRequestValidationMail(Team $team) - { - global $YEAR; - - $content = self::getTemplate("request_validation"); - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - $content = preg_replace("#{PROBLEM}#", $team->getProblem(), $content); - $content = preg_replace("#{ACCESS_CODE}#", $team->getAccessCode(), $content); - - self::broadcastToAdmins("Demande de validation – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendValidateTeam($team, $message) - { - global $YEAR; - - $content = self::getTemplate("validate_team"); - if (strlen($message) > 0) - $message = " L'équipe d'organisation vous transmet le message suivant :\n\n" . $message; - $message = preg_replace("#\n#", "
\n", $message); - $content = preg_replace("#{MESSAGE}#", $message, $content); - - self::broadcastToTeam($team, "Équipe validée – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendUnvalidateTeam($team, $message) - { - global $YEAR; - - $content = self::getTemplate("unvalidate_team"); - if (strlen($message) > 0) - $message = " L'équipe d'organisation vous transmet le message suivant :\n\n" . $message; - $message = preg_replace("#\n#", "
\n", $message); - $content = preg_replace("#{MESSAGE}#", $message, $content); - - self::broadcastToTeam($team, "Équipe non validée – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendNewVideo(NewVideo $video, Team $team) - { - global $YEAR; - - $content = self::getTemplate("new_video"); - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - $content = preg_replace("#{PROBLEM}#", $team->getProblem(), $content); - $content = preg_replace("#{VIDEO_LINK}#", $video->link, $content); - self::broadcastToAdmins("Nouvelle vidéo – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function sendNewAnswer(NewAnswer $video, Team $team) - { - global $YEAR; - - $content = self::getTemplate("new_answer"); - $content = preg_replace("#{TEAM_NAME}#", $team->getName(), $content); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - $dest = Team::fromId($team->getVideoTeamIds()[$video->team - 1]); - $content = preg_replace("#{DEST_TEAM_NAME}#", $dest->getName(), $content); - $content = preg_replace("#{DEST_TRIGRAM}#", $dest->getTrigram(), $content); - $content = preg_replace("#{PROBLEM}#", $team->getProblem(), $content); - $content = preg_replace("#{VIDEO_LINK}#", $video->link, $content); - - self::broadcastToAdmins("Nouvelle vidéo de réponse – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } - - public static function validateVideo(Video $video, $message) - { - global $YEAR; - - $team = Team::fromId($video->getTeam()); - - $template = "video_"; - $template .= $video->getValidation() == Video::ACCEPTED ? "accepted" : "rejected"; - $template .= $video->getReason() == Reason::SOLUTION ? "_solution" : "_answer"; - $content = self::getTemplate($template); - $content = preg_replace("#{TRIGRAM}#", $team->getTrigram(), $content); - $content = preg_replace("#{PROBLEM}#", $team->getProblem(), $content); - $content = preg_replace("#{VIDEO_LINK}#", $video->getLink(), $content); - if (strlen($message) > 0) - $message = " L'équipe d'organisation vous transmet le message suivant :\n\n" . $message . "\n\n"; - $message = preg_replace("#\n#", "
\n", $message); - $content = preg_replace("#{MESSAGE}#", $message, $content); - - self::broadcastToTeam($team, ($video->getValidation() == Video::REJECTED ? "Vidéo refusée " : "Vidéo acceptée ") - . $team->getTrigram() . " – Correspondances des Jeunes Mathématicien·ne·s $YEAR - " . ($YEAR + 1), $content); - } -} diff --git a/server_files/services/mail_templates/add_admin.html b/server_files/services/mail_templates/add_admin.html deleted file mode 100644 index 1f4745d..0000000 --- a/server_files/services/mail_templates/add_admin.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Administrateur des Correspondances des Jeunes Mathématicien·ne·s - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous recevez ce message (envoyé automatiquement) car vous êtes administrateur pour les Correspondances des Jeunes Mathématicien·ne·s. -Veuillez trouver ci-dessous vos informations d'utilisateur pour le site officiel des inscriptions. Elles vous permettront de gérer les inscriptions des équipes.
-
-Votre mot de passe est : {PASSWORD}
-Vous pouvez vous connecter ici : {URL_BASE}/connexion
-
-Notez bien que ce mot de passe est temporaire, et pour des raisons de sécurité vous devrez le changer lors de votre prochaine connexion sur le site.
-
-Merci beaucoup pour votre aide !
-
-L'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/add_team.html b/server_files/services/mail_templates/add_team.html deleted file mode 100644 index 0b2b0a6..0000000 --- a/server_files/services/mail_templates/add_team.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Nouvelle équipe Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous venez de créer l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour les Correspondances des Jeunes Mathématicien·ne·s -{PROBLEM} et nous vous en remercions.
-Afin de permettre aux autres membres de votre équipe de vous rejoindre, veuillez leur transmettre le code d'accès : -{ACCESS_CODE}
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/change_email_address.html b/server_files/services/mail_templates/change_email_address.html deleted file mode 100644 index b61c801..0000000 --- a/server_files/services/mail_templates/change_email_address.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Changement d'adresse e-mail – Correspondances des Jeunes Mathématicien·ne·s - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous venez de changer votre adresse e-mail. Veuillez désormais la confirmer en cliquant ici : {URL_BASE}/confirmer-mail/{TOKEN}
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/change_password.html b/server_files/services/mail_templates/change_password.html deleted file mode 100644 index f659999..0000000 --- a/server_files/services/mail_templates/change_password.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Mot de passe changé – Correspondances des Jeunes Mathématicien·ne·s - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Nous vous informons que votre mot de passe vient d'être modifié. Si vous n'êtes pas à l'origine de cette manipulation, -veuillez immédiatement vérifier vos accès à votre boîte mail et changer votre mot de passe sur la plateforme -d'inscription.
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/confirm_email.html b/server_files/services/mail_templates/confirm_email.html deleted file mode 100644 index 471323f..0000000 --- a/server_files/services/mail_templates/confirm_email.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - Inscription aux Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous êtes inscrit aux Correspondances des Jeunes Mathématicien·ne·s {YEAR} et nous vous en remercions.
-Pour valider votre adresse e-mail, veuillez cliquer sur le lien : {URL_BASE}/confirmer-mail/{TOKEN}
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/forgotten_password.html b/server_files/services/mail_templates/forgotten_password.html deleted file mode 100644 index a5aa18a..0000000 --- a/server_files/services/mail_templates/forgotten_password.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - Mot de passe oublié – Correspondances des Jeunes Mathématicien·ne·s - - -Bonjour,
-
-Vous avez indiqué avoir oublié votre mot de passe. Veuillez cliquer ici pour le réinitialiser : {URL_BASE}/connexion/reinitialiser_mdp/{TOKEN}
-
-Si vous n'êtes pas à l'origine de cette manipulation, vous pouvez ignorer ce message.
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/join_team.html b/server_files/services/mail_templates/join_team.html deleted file mode 100644 index aa63d65..0000000 --- a/server_files/services/mail_templates/join_team.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - Équipe rejointe – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous venez de rejoindre l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour les Correspondances des Jeunes Mathématicien·ne·s -{PROBLEM} et nous vous en remercions.
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/new_answer.html b/server_files/services/mail_templates/new_answer.html deleted file mode 100644 index 3f9fb3c..0000000 --- a/server_files/services/mail_templates/new_answer.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - Nouvelle vidéo – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-L'équipe « {TEAM_NAME} » ({TRIGRAM}) vient d'ajouter une vidéo de réponse destinée à l'équipe « {DEST_TEAM_NAME} » ({DEST_TRIGRAM}) -pour le problème {PROBLEM} des Correspondances des Jeunes Mathématicien·ne·s : {VIDEO_LINK}. -Vous êtes désormais invité avant que quelqu'un d'autre ne le fasse à accepter ou refuser cette vidéo via la plateforme d'inscription (accessible après connexion) : -{URL_BASE}/suivi-correspondances
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/new_video.html b/server_files/services/mail_templates/new_video.html deleted file mode 100644 index b98d2d1..0000000 --- a/server_files/services/mail_templates/new_video.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Nouvelle vidéo – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-L'équipe « {TEAM_NAME} » ({TRIGRAM}) vient d'ajouter une vidéo pour le problème {PROBLEM} des Correspondances des Jeunes Mathématicien·ne·s : {VIDEO_LINK}. -Vous êtes désormais invité avant que quelqu'un d'autre ne le fasse à accepter ou refuser cette vidéo via la plateforme d'inscription (accessible après connexion) : -{URL_BASE}/suivi-correspondances
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/register.html b/server_files/services/mail_templates/register.html deleted file mode 100644 index ab699c9..0000000 --- a/server_files/services/mail_templates/register.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Inscription aux Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Vous venez de vous inscrire aux Correspondances des Jeunes Mathématicien·ne·s {YEAR} et nous vous en remercions.
-Pour valider votre adresse e-mail, veuillez cliquer sur le lien : {URL_BASE}/confirmer-mail/{TOKEN}
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/request_validation.html b/server_files/services/mail_templates/request_validation.html deleted file mode 100644 index 137166e..0000000 --- a/server_files/services/mail_templates/request_validation.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - Demande de validation - Correspondances des Jeunes Mathématicien·ne·s - - -Bonjour {FIRST_NAME} {SURNAME},
-
-L'équipe « {TEAM_NAME} » ({TRIGRAM}) vient de demander à valider son équipe pour participer au problème n°{PROBLEM} des -Correspondances des Jeunes Mathématicien·ne·s. Vous pouvez décider d'accepter ou de refuser l'équipe en vous rendant sur -la page de l'équipe : {URL_BASE}/equipe/{TRIGRAM}
-
-Cordialement,
-
-L'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/unvalidate_team.html b/server_files/services/mail_templates/unvalidate_team.html deleted file mode 100644 index 3c80990..0000000 --- a/server_files/services/mail_templates/unvalidate_team.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Équipe non validée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Maleureusement, votre équipe « {TEAM_NAME} » ({TRIGRAM}) n'a pas été validée. Veuillez vérifier que vos autorisations -de droit à l'image sont correctes. -{MESSAGE}
-
-N'hésitez pas à nous contacter à l'adresse contact@correspondances-maths.fr -pour plus d'informations. -
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/validate_team.html b/server_files/services/mail_templates/validate_team.html deleted file mode 100644 index f34caab..0000000 --- a/server_files/services/mail_templates/validate_team.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Équipe validée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Félicitations ! Votre équipe « {TEAM_NAME} » ({TRIGRAM}) est désormais validée ! Vous êtes désormais apte à travailler sur -votre problème. Lorsque les Correspondances auront débutées, vous pourrez soumettre votre vidéo sur la plateforme d'inscription. -{MESSAGE}
-
-Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/video_accepted_answer.html b/server_files/services/mail_templates/video_accepted_answer.html deleted file mode 100644 index a3bfe08..0000000 --- a/server_files/services/mail_templates/video_accepted_answer.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Vidéo acceptée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Félicitations, votre vidéo de réponse pour le problème {PROBLEM} a été validée ! Pour rappel, vous aviez soumis ce lien : {VIDEO_LINK}.
-Vous avez à présent terminé l'aventure des Correspondances. Bravo à vous ! Nous vous recontacterons dans les prochains jours pour vous tenir au courant des résultats.
-Si toutefois vous le souhaitez, vous pouvez à nouveau soumettre une vidéo avant la fin de la phase. Cette nouvelle vidéo ne remplacera l'actuelle qu'au moment de la validation de celle-ci.
-
-N'oubliez pas de contrôler que les paramètres de diffusion de vidéo sont cohérents avec ce que vous souhaitez : {URL_BASE}/mon-equipe
-
-{MESSAGE} -Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/video_accepted_solution.html b/server_files/services/mail_templates/video_accepted_solution.html deleted file mode 100644 index 4c62be8..0000000 --- a/server_files/services/mail_templates/video_accepted_solution.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Vidéo acceptée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Félicitations, votre vidéo pour le problème {PROBLEM} a été validée ! Pour rappel, vous aviez soumis ce lien : {VIDEO_LINK}.
-Votre travail est à présent terminé, et vous pouvez attendre les prochaines phases. Bravo à vous !
-Si toutefois vous le souhaitez, vous pouvez à nouveau soumettre une vidéo avant la fin de la phase. Cette nouvelle vidéo ne remplacera l'actuelle qu'au moment de la validation de celle-ci.
-
-N'oubliez pas de contrôler que les paramètres de diffusion de vidéo sont cohérents avec ce que vous souhaitez : {URL_BASE}/mon-equipe
-
-{MESSAGE} -Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/video_rejected_answer.html b/server_files/services/mail_templates/video_rejected_answer.html deleted file mode 100644 index fdf4700..0000000 --- a/server_files/services/mail_templates/video_rejected_answer.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Vidéo refusée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Malheureusement, votre vidéo de réponse pour le problème {PROBLEM} n'a pas été validée. Pour rappel, vous aviez soumis -ce lien : {VIDEO_LINK}.
-Si vous aviez soumis une précédente vidéo qui a été validée, elle reste conservée. -Vous êtes désormais invités à retravailler vos réponses ou votre présentation orale afin que votre prestation soit -validée par les organisateurs. N'hésitez pas à nous contacter à -contact@correspondances-maths.fr si vous souhaitez avoir plus -d'informations ou contester ce refus.
-
-{MESSAGE} -Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/services/mail_templates/video_rejected_solution.html b/server_files/services/mail_templates/video_rejected_solution.html deleted file mode 100644 index 3fe16da..0000000 --- a/server_files/services/mail_templates/video_rejected_solution.html +++ /dev/null @@ -1,23 +0,0 @@ - - - - - Vidéo refusée – Correspondances des Jeunes Mathématicien·ne·s {YEAR} - - -Bonjour {FIRST_NAME} {SURNAME},
-
-Malheureusement, votre vidéo pour le problème {PROBLEM} n'a pas été validée. Pour rappel, vous aviez soumis ce lien : -{VIDEO_LINK}.
-Si vous aviez soumis une précédente vidéo qui a été validée, elle reste conservée. -Vous êtes désormais invités à retravailler vos résultats ou votre présentation orale afin que votre prestation soit -validée par les organisateurs. N'hésitez pas à nous contacter à -contact@correspondances-maths.fr si vous souhaitez avoir plus -d'informations ou contester ce refus.
-
-{MESSAGE} -Cordialement,
-
-Le comité d'organisation des Correspondances des Jeunes Mathématicien·ne·s - - \ No newline at end of file diff --git a/server_files/utils.php b/server_files/utils.php deleted file mode 100644 index 6363e82..0000000 --- a/server_files/utils.php +++ /dev/null @@ -1,48 +0,0 @@ - - -
-

Liste des administrateurs

-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- Nom - - Prénom - - Adresse e-mail -
- getSurname() ?>"> - getSurname() ?> - - - getSurname() ?>"> - getFirstName() ?> - - - - getEmail() ?> - -
- Nom - - Prénom - - Adresse e-mail -
- - - -
-

Ajouter un administrateur

-
- - -
- Administrateur ajouté avec succès ! Ses identifiants ont été transmis par mail. -
- - -
-
-
- - -
- -
- - -
-
- -
-
- - -
-
- -
- -
-
- - diff --git a/server_files/views/ajouter_equipe.php b/server_files/views/ajouter_equipe.php deleted file mode 100644 index df1618a..0000000 --- a/server_files/views/ajouter_equipe.php +++ /dev/null @@ -1,78 +0,0 @@ - - -
-

Ajouter une équipe

-
- - -
- Votre équipe a bien été créée ! Voici le code d'accès à transmettre aux autres membres de votre équipe : - access_code ?> -
- -
- Vous êtes déjà dans une équipe. -
-= $CONFIG->getInscriptionDate()) { ?> -
- La date limite d'inscription est dépassée. -
- - - 0) { ?> -
- Vous êtes déjà inscrit dans une équipe. Vous pouvez toutefois encadrer plusieurs équipes. -
- - -
- Chacune des informations pourra être modifiée avant que l'équipe tant que l'équipe n'est pas validée. -
- -
-
-
- - -
- -
- - -
-
- -
- - -
- - - allow_other_teams ? "checked" : "" ?> required/>
- - - allow_publish ? "checked" : "" ?> /> - -
- Cette dernière option est modifiable à tout moment, et permet à Animath de diffuser les vidéos primées. -
- -
- -
-
- - - diff --git a/server_files/views/calendrier.php b/server_files/views/calendrier.php deleted file mode 100644 index 995eed9..0000000 --- a/server_files/views/calendrier.php +++ /dev/null @@ -1,138 +0,0 @@ - - -
-

Calendrier

-
- - - -
-
- -
- - -
-
- -
- -
- - -
-
- - -
-
- -
- -
- - -
-
- - -
-
- -
- -
- - -
-
- - -
-
- -
- -
- - -
-
- - -
-
- -
- -
-
- - - -
getInscriptionDate() ? "warning" : "success" ?>"> - : - getInscriptionDate(), true) ?> -
- -
"> - : - Du getStartPhase1Date(), true) ?> au - getEndPhase1Date(), true) ?> -
- -
"> - : - Du getStartPhase2Date(), true) ?> au - getEndPhase2Date(), true) ?> -
- -
"> - : - Du getStartPhase3Date(), true) ?> au - getEndPhase3Date(), true) ?> -
- -
"> - : - Du getStartPhase4Date(), true) ?> au - getEndPhase4Date(), true) ?> -
- - - - - - - - -
- - - - - - - -
-

Répondre aux questions

-
- - -
- Votre vidéo a bien été envoyée ! -
- - -
- Pour clore vos Correspondances, vous devez produire, pour chaque vidéo reçue d'une autre équipe, une vidéo de - synthèse d'au plus 4 minutes. - Cette vidéo doit mettre en perspective de la vidéo initiale en tenant compte de l'échange qui a eu lieu. - Vous devez mettre en valeur l’échange questions/réponses, et montrer l'évolution de la résolution au problème. -
- -
- Date limite de soumission : getEndPhase4Date(), true) ?> -
- - -
-

Vidéo de l'équipe getName() ?> (getTrigram() ?>) :

-
- Lien de la vidéo de présentation de la solution au problème : - getLink() ?> -
- getLink()) ?> - -
Questions échangées :
- getQuestion(), Question::DEFAULT_QUESTIONS[0]) - && !strcmp($questions[2]->getQuestion(), Question::DEFAULT_QUESTIONS[1]) - && !strcmp($questions[3]->getQuestion(), Question::DEFAULT_QUESTIONS[2])) { ?> -
- L'équipe n'a malheureusement transmis aucune question. Vous n'avez donc pas de réponse à donner. -
- 0 && $question->getQuestion() === null) - continue; - ?> -
- getNumber() . " :" ?> - getQuestion() ?>
- getAttachedFile() !== null) { ?> - Pièce jointe attachée : - Télécharger
- - Réponse : getAnswer() ?>
- getAttachedFileAnswer() !== null) { ?> - Pièce jointe attachée : - Télécharger
- -
- -
-
Vidéo de réponse :
- - getLink(); - echo "
Lien de la vidéo déjà envoyée : $link (version " . $answer->getVersion() . ")
\n"; - displayVideo($link); - switch ($answer->getValidation()) { - case 0: - echo "
La vidéo n'a pas encore été vérifiée par l'équipe d'organisation.
"; - break; - case 1: - echo "
La vidéo a été acceptée par l'équipe d'organisation.
"; - break; - case -1: - echo "
La vidéo a été rejetée par l'équipe d'organisation.
"; - break; - } - } - if ($answer_validated != null && $answer_validated->getId() != $answer->getId()) { - $link = $answer_validated->getLink(); - echo "
\n
Lien de la dernière vidéo validée : $link
\n"; - displayVideo($link); - } - ?> - -
- -
-
- - -
-
- -
- - - - -
-
- Le mail de récupération de mot de passe a bien été envoyé."; - elseif (isset($reset_password) && isset($_POST["password"])) - echo "
Le mot de passe a bien été changé. Vous pouvez désormais vous connecter.
"; - elseif (isset($_GET["confirmation-mail"])) - echo "
Le mail a bien été renvoyé.
"; - else if (isset($logging_in_user)) { - echo "
Connexion réussie !
"; - require_once "footer.php"; - } else if (isset($_SESSION["user_id"])) { - echo "
Vous êtes déjà connecté !
"; - require_once "footer.php"; - } -} - -if (isset($_GET["mdp_oublie"])) { ?> -
-

Réinitialisation du mot de passe

- - - -
-user != null && ($has_error || !isset($_POST["password"]))) { ?> -
-

Connexion

- "/> -
- - -
-
- - -
- -
- - -
-

Connexion

-
-
- - -
-
- - -
- -
- - - - diff --git a/server_files/views/envoyer_video.php b/server_files/views/envoyer_video.php deleted file mode 100644 index dfa8b23..0000000 --- a/server_files/views/envoyer_video.php +++ /dev/null @@ -1,87 +0,0 @@ - - -
-

Envoyer la vidéo de solution

-
- - -
- Votre vidéo a bien été envoyée ! -
- - -
-
    -
  • Une fois vos travaux sur votre problème terminés, vous êtes invités dans le cadre des Correspondances à tourner - une vidéo dans laquelle vous présentez vos résultats.
  • -
  • La vidéo doit durer au maximum 8 minutes.
  • -
  • Un travail de recherche, en équipe sur les problèmes, supervisé par l'encadrant·e, est attendu.
  • -
  • Au début de la vidéo, une brève présentation de l'énoncé est appréciée.
  • -
  • L'équipe doit présenter ses réponses trouvées aux questions de l'énoncé.
  • -
  • Toutes les plateformes d'hébergement vidéo sont supportées. Néanmoins, les plateformes - Viméo, YouTube - et Dailymotion permettent une prévisualisation de la vidéo. - Cette liste pourra être étendue si besoin est.
  • -
  • Les liens de vos vidéos sont soumis à validation à l'équipe d'organisation.
  • -
-
- -
- Date limite de soumission : getEndPhase1Date(), true) ?> -
- - -
- Vous avez soumis précédemment une vidéo, qui a été refusée par l'équipe d'organisation. Les détails ont du vous être transmis par mail. - Vous êtes désormais invités à poster une nouvelle vidéo, conforme aux attentes. En particulier, vérifiez que votre vidéo n'excède pas - la durée limite de 8 minutes. -
- - -getLink(); - echo "
Lien de la vidéo déjà envoyée : $link (version " . $video->getVersion() . ")
\n"; - displayVideo($link); - switch ($video->getValidation()) { - case 0: - echo "
La vidéo n'a pas encore été vérifiée par l'équipe d'organisation.
"; - break; - case 1: - echo "
La vidéo a été acceptée par l'équipe d'organisation.
"; - break; - case -1: - echo "
La vidéo a été rejetée par l'équipe d'organisation.
"; - break; - } -} -if ($video_validated != null && $video_validated->getId() != $video->getId()) { - $link = $video_validated->getLink(); - echo "
\n
Lien de la dernière vidéo validée : $link
\n"; - displayVideo($link); -} -?> - -
- -
-
-
- - -
-
- -
- - - - -
- - - -
-

Informations sur l'équipe

-
- -
- Nom de l'équipe : getName() ?> -
-
- Trigramme : getTrigram() ?> -
-
- getInscriptionDate() && $team->getValidationStatus() == ValidationStatus::NOT_READY) { ?> - -
- -
- - Problème : - getProblem() == 0 ? "Pas de problème choisi" : $team->getProblem() ?> - - -
-
getValidationStatus() == ValidationStatus::WAITING ? "warning" : "danger") ?>"> - Validation de l'équipe - : getValidationStatus()) ?> -
-
- getEncadrantId() !== null) { - $encadrant = User::fromId($team->getEncadrantId()); - $id = $encadrant->getId(); - echo "Encadrant : getFirstName() . " " . $encadrant->getSurname() . "\">" . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; - } - for ($i = 1; $i <= 5; ++$i) { - if ($team->getParticipants()[$i - 1] == NULL) - continue; - $participant = User::fromId($team->getParticipants()[$i - 1]); - $id = $participant->getId(); - echo "Participant $i : getFirstName() . " " . $participant->getSurname() . "\">" . $participant->getFirstName() . " " . $participant->getSurname() . "
"; - } - ?> -
-
- Autorise Animath à diffuser les vidéos : allowPublish() ? "oui" : "non" ?> -
- - - -getValidationStatus() == ValidationStatus::VALIDATED && $team->getSolution() != null && $team->getSolution()->getValidation() == ValidationStatus::VALIDATED - 1) { ?> -
- - - -
-
-
-
- - -
-
-
- - - -
-
- - -
- -

Autorisations de droit à l'image

- - - -
- -
- -getValidationStatus() == ValidationStatus::WAITING) { ?> -
-
-
- - -
- -
-
- - -
-
-
- getValidationStatus() == ValidationStatus::NOT_READY) { ?> -
-
- -
- \ No newline at end of file diff --git a/server_files/views/exporter_donnees.php b/server_files/views/exporter_donnees.php deleted file mode 100644 index 597f711..0000000 --- a/server_files/views/exporter_donnees.php +++ /dev/null @@ -1,33 +0,0 @@ - - -
-

Exporter les données

-
- -
- -
- -
- -
- -
- -
- -
- -
- -
- -

Ce site a enregistré getViews() ?> visites.

- - - - - -
-
-
-
- Ce site a été conçu pour Animath, avec amour et passion. Il est récent et il est possible que - certaines pages ne fonctionnent pas correctement. Si vous remarquez des bugs, merci de les signaler à - l'adresse contact@correspondances-maths.fr.
- © Correspondances de Jeunes Mathématicien·ne·s -
-
-
- - - diff --git a/server_files/views/header.php b/server_files/views/header.php deleted file mode 100644 index 57b78b8..0000000 --- a/server_files/views/header.php +++ /dev/null @@ -1,177 +0,0 @@ -incrViews() ?> - - - - - - !"> - - - - - Site d'inscription pour les Correspondances des Jeunes Mathématicien·ne·s <?= $YEAR . " - " . ($YEAR + 1) ?> - - - - - - - - - - -
-
-
- - -
- Erreur : -
- -
- Le site est actuellement en maintenance. Veuillez réessayer ultérieurement. -
- - -
-
-

- Bienvenue sur le site d'inscription aux - Correspondances des Jeunes Mathématicien·ne·s ! -

-
-
-
-
-

- Tu souhaites participer aux Correspondances ? -
- Ton équipe est déjà formée ? -

-
- -
- -
-
Comment ça marche ?
-

- Pour participer aux Correspondances, il suffit de créer un compte sur la rubrique Inscription. - Vous devrez ensuite confirmer votre adresse e-mail. -

- -

- Vous pouvez accéder à votre compte via la rubrique Connexion. Une fois connecté, vous pourrez créer une équipe - ou en rejoindre une déjà créée par l'un de vos camarades via un code d'accès qui vous aura été transmis. Vous serez ensuite - invité à soumettre une autorisation de droit à l'image, indispensable au bon déroulement des Correspondances. Une fois que votre équipe - comporte au moins 3 participants (maximum 5) et un encadrant, vous pourrez demander à valider votre équipe pour - être apte à travailler sur le problème de votre choix. -

- -
- Attention aux dates ! Si vous ne finalisez pas votre inscription dans le délai indiqué, vous - ne pourrez malheureusement pas participer aux Correspondances. -
- -
- Si votre équipe est déjà formée mais que vous peinez à trouver un encadrant, n'hésitez pas à nous contacter à l'adresse - contact@correspondances-maths.fr pour que nous vous aidions à - vous mettre éventuellement en contact avec un encadrant de votre région. -
-
- -
\ No newline at end of file diff --git a/server_files/views/index.php b/server_files/views/index.php deleted file mode 100644 index 129d4e5..0000000 --- a/server_files/views/index.php +++ /dev/null @@ -1,76 +0,0 @@ - -
- - - -
- -
- -
-
-getInscriptionDate()) { - if ($_SESSION["teams"] == null || sizeof($_SESSION["teams"]) == 0) { ?> -
- Pour participer aux Correspondances, vous devez rejoindre une équipe. Cliquez ici - pour rejoindre une équipe, et ici pour en créer une. -
- getParticipants()[2] == null || $_SESSION["team"]->getEncadrantId() == null) { ?> -
- Votre équipe doit comporter au moins 3 personnes et un encadrant pour pouvoir participer. Pensez - à transmettre - le code d'accès aux autres membres de votre équipe, qui doivent elles aussi s'inscrire sur la - plateforme : - getAccessCode() ?> -
- getProblem() == 0) { ?> -
- Vous devez indiquer problème pour participer. Pensez à le spécifier dans la page Mon équipe. -
- getValidationStatus() == ValidationStatus::NOT_READY) { ?> -
- Pensez à demander la validation de votre équipe pour pouvoir participer aux Correspondances. - Chaque membre de votre - équipe doit pour cela avoir soumis son autorisation de droit à l'image sur la page Mon compte. - Les encadrants ne sont pas concernés. -
- -
- Vous avez soumis précédemment une vidéo pour l'équipe getName() ?>, qui a été refusée par - l'équipe d'organisation. Les détails ont du vous être transmis par mail. - Vous êtes désormais invités à poster une nouvelle vidéo sur la page dédiée, conforme aux - attentes. En particulier, vérifiez - que votre vidéo n'excède pas la durée limite de 8 minutes. -
- getIndexPage()); - - if (isset($_SESSION["user_id"]) && $_SESSION["role"] == Role::ADMIN) { ?> -
- - Modifier la page - - - -
-

getFirstName() . " " . $user->getSurname() ?>

-
- - -
- La personne a bien été exclue de l'équipe ! -
- -
- La personne a bien rejoint l'équipe ! -
- - -
- Rôle : getRole()) ?> -
- -getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { ?> -
- Équipe - : getTrigram() . "\">" - . $team->getName() . " (" . $team->getTrigram() . ")" ?> - -
-
-
- - -
-
-
- - - -
-
- getValidationStatus() == ValidationStatus::NOT_READY) { ?> -
- - Virer de l'équipe -
- -
- - -getRole() == Role::PARTICIPANT) { ?> -
- Lycée : getSchool() ?>
- Ville : getCity() ?>
- Pays : getCountry() ?>
- Classe : getClass()) ?> -
-getDescription() != "") { ?> -
- Activité professionnelle : getDescription() ?> -
- - -
- Adresse e-mail : getEmail() ?> - getConfirmEmailToken() == null ? "" : "(non validée)" ?> -
- -
- getRole() == Role::ADMIN ? "Reçoit des notifications par mail :" - : "Autorise Animath à envoyer des mails :" ?> doReceiveAnimathMails() ? "oui" : "non" ?> -
- -getRole() == Role::PARTICIPANT) { ?> -
- -
-

Autorisation de droit à l'image :

-
- getId()) { - if ($user->getRole() != Role::ADMIN && $team == null) { ?> -
- -
- -
- - -
- -
- getSurname() ?>"/> -
- - -
-

Formulaire d'inscription

-
- - -
- Vous êtes bien inscrit ! Merci désormais de confirmer votre boîte mail pour valider votre adresse. Pensez à vérifier - vos courriers indésirables. -
- -
- Vous êtes déjà connecté ! -
-= $CONFIG->getInscriptionDate()) { ?> -
- La date limite d'inscription est dépassée. -
- - -
-
- - -
- -
-
- - -
- -
- - -
-
- -
- L'adresse mail sert uniquement à recevoir les informations de déroulement des Correspondances. -
- -
-
- - -
-
- -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
-
-
- - "/> -
-
- - -
-
- -
- - - -
- - - receive_animath_mails ? "checked" : "" ?> />

- -
- -
-
- - - - - - \ No newline at end of file diff --git a/server_files/views/ma_participation.php b/server_files/views/ma_participation.php deleted file mode 100644 index 3084198..0000000 --- a/server_files/views/ma_participation.php +++ /dev/null @@ -1,132 +0,0 @@ - -= Phase::PHASE1) { ?> -
-

Ma participation

-
- -
-

Vidéo de solution proposée :

-
- Lien de la vidéo : getLink() ?> -
- getLink()) ?> -
- = Phase::PHASE3) { ?> -

Questions reçues :

- getFrom()); - $answer = Video::getVideo($asker->getVideoTeamIds()[0] == $team->getId() ? Reason::ANSWER1 : Reason::ANSWER2, - $asker, Video::ACCEPTED); - ?> -
Questions de l'équipe getName() ?> (getTrigram() ?>) :
- getQuestion() === null) - continue; - ?> -
- - getQuestion() ?> -
- getAttachedFile() !== null) { ?> - Pièce jointe attachée : - Télécharger -
- - Réponse : getAnswer() ?>
- getAttachedFileAnswer() !== null) { ?> - Pièce jointe attachée : - Télécharger -
- -
- -
- Phase::PHASE4 && $answer != null) { ?> -
Vidéo de réponse proposée par l'équipe :
-
- Lien de la vidéo : getLink() ?> -
- getLink()) ?> - " : "" ?> - - - - -
- - = Phase::PHASE2) { ?> -
-
- getVideoTeamIds()[$i]); - if ($defender == null) - continue; - $sol = Video::getVideo(Reason::SOLUTION, $defender, Video::ACCEPTED); - $answer = Video::getVideo($i == 0 ? Reason::ANSWER1 : Reason::ANSWER2, $team, Video::ACCEPTED); - $questions = Question::getQuestions($team, $defender); - ?> -

Vidéo de solution proposée par l'équipe getName() ?> - (getTrigram() ?>) :

-
- Lien de la vidéo : getLink() ?> -
- getLink()) ?> -
-
Vos questions :
-
- getQuestion() === null) - continue; - ?> -
- getNumber() ? "Question " . $question->getNumber() : "Remarques générales" ?> : \n", $question->getQuestion()) ?> -
- getAttachedFile() !== null) { ?> - Pièce jointe attachée : - Télécharger -
- - = Phase::PHASE4) { ?> - Réponse : \n", $question->getAnswer()) ?>
- getAttachedFile() !== null) { ?> - Pièce jointe attachée : - Télécharger -
- - -
- -
- = Phase::PHASE4 && $answer != null) { ?> -
Votre vidéo de réponse :
-
- Lien de la vidéo : getLink() ?> -
- getLink()) ?> - - " : "" ?> - - - - - - -
-

Mon compte

-
- - -
- Le fichier a été correctement envoyé ! -
- - - -
- Votre compte a bien été mis à jour ! -
- getEmail() != $my_account->email) { ?> -
- Votre adresse mail a bien été changée. Veuillez vérifier votre boîte mail pour valider votre nouvelle - adresse, vous en aurez besoin pour vous reconnecter. -
- - - -
- -
-
- - -
- -
- - -
-
- -
-
- - -
-
- - - doReceiveAnimathMails() ? "checked" : "" ?> /> - - getRole() == Role::PARTICIPANT) { ?> -
-
- - -
-
- - -
-
- -
-
- - -
-
- - -
-
- - getRole() == Role::ENCADRANT) { ?> - -
- - -
- - - -
- -
-
- -
- -
- -
-
- - -
- -
- - -
- -
- - -
-
- -
- -
-
- -getRole() == Role::PARTICIPANT) { - $not_validated = $_SESSION["team"]->getValidationStatus() == ValidationStatus::NOT_READY - && date("Y-m-d H:i:s") < $CONFIG->getInscriptionDate(); - ?> -
-
-

Autorisation de droit à l'image

-
- - Ce document peut être modifié tant que l'équipe n'est pas validée. - -
- Modèle d'autorisation de droit à l'image : - majeur - mineur -
- - - -
- Le fichier doit être au format PDF, PNG ou JPEG et doit peser moins de 2 Mo. -
-
- -
-
- - -
-
- -
- -
-
- - - - \ No newline at end of file diff --git a/server_files/views/mon_equipe.php b/server_files/views/mon_equipe.php deleted file mode 100644 index 3c58e77..0000000 --- a/server_files/views/mon_equipe.php +++ /dev/null @@ -1,135 +0,0 @@ - - -
-

Mon équipe

-
- -
- Nom de l'équipe : getName() ?> -
-
- Trigramme : getTrigram() ?> -
-
- Problème : - getProblem() == 0 ? "Pas de problème choisi" : $team->getProblem() ?> -
-
- getEncadrantId() !== null) { - $encadrant = User::fromId($team->getEncadrantId()); - $id = $encadrant->getId(); - echo "Encadrant : " . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; - } - for ($i = 1; $i <= 5; ++$i) { - if ($team->getParticipants()[$i - 1] == NULL) - continue; - $participant = User::fromId($team->getParticipants()[$i - 1]); - $id = $participant->getId(); - echo "Participant $i : " . $participant->getFirstName() . " " . $participant->getSurname() . "
"; - } - - ?> -
-
- Code d'accès : getAccessCode() ?> -
-
- - Autorise Animath à diffuser mes vidéos à la fin des Correspondances : - allowPublish() ? "oui" : "non" ?> (changer) -
- -= $CONFIG->getInscriptionDate() && $team->getValidationStatus() == ValidationStatus::NOT_READY) { ?> -
- La date limite d'inscription est dépassée, vous ne pouvez plus demander la validation de votre équipe. -
-getValidationStatus() == ValidationStatus::NOT_READY) { ?> - -
-
-
- - -
- -
- - -
-
- -
- - -
- -
- -
-
- - - - getValidationStatus() == ValidationStatus::NOT_READY && date("Y-m-d H:i:s") <= $CONFIG->getInscriptionDate()) { ?> - - - - - - getValidationStatus() == ValidationStatus::NOT_READY) { ?> -
- -
- -
- - -
-
- - -
- Attention ! Une fois votre équipe validée, vous ne pourrez plus modifier le nom - de l'équipe, le trigramme, le problème sur lequel vous souhaitez travailler ou la composition de l'équipe. -
- -
- -
-
- Pour demander à valider votre équipe, vous devez avoir au moins un encadrant, trois participants, - choisi un problème et soumis une autorisation de droit à l'image par participant. -
- - getValidationStatus() == ValidationStatus::WAITING) { ?> -
- Votre équipe est en attente de validation. -
- - -
- -

Autorisations de l'équipe

- - - - - \ No newline at end of file diff --git a/server_files/views/poser_questions.php b/server_files/views/poser_questions.php deleted file mode 100644 index 013d788..0000000 --- a/server_files/views/poser_questions.php +++ /dev/null @@ -1,98 +0,0 @@ - - -
-

Poser des questions

-
- - -
- Vos questions ont bien été mises à jour ! -
- - -
- Pour cette deuxième phase des Correspondances, vous êtes invités à visionner les vidéos de solution de deux autres - équipes, qui ont travaillé sur le même problème que vous. Vous devez désormais poser entre 3 et 6 questions, portant - sur la présentation de l'équipe. Chaque question peut-être accompagnée d'une pièce jointe (dessin, schéma, ...) - sous toute forme (PDF, image, archive, ...) tant que le poids ne dépasse pas 2 Mo. Si vous le souhaitez, vous pouvez - adresser aux équipes des remarques plus générales. -
- -
- Date limite de soumission des questions : getEndPhase2Date(), true) ?> -
- -
-

Veuillez toujours enregistrer votre travail ailleurs que sur la plateforme !

-
- - -
-

Questions pour l'équipe getName() ?> (getTrigram() ?>) :

-
- Lien de la vidéo : getLink() ?> -
- getLink()) ?> -
-
- - - getQuestion() == null && $j > 0) { ?> - " - onclick="addQuestion(, )">Ajouter une question -
- -
;"> -
- - -
- - getAttachedFile() != null) { ?> -
-
- Pièce jointe : Télécharger -
- - -
- - -
-
- - - - - -
-
- - - - -
-

- -

-
- -
- -

Équipes inscrites 0 ? "pour ce problème" : "sans problème choisi" ?> :

- - - - - - - - 0) { ?> - - - - - - - - - - - 0) { ?> - - - - - - - - - - - 0) { ?> - - - - -
- Équipe - - Trigramme - - Date d'inscription - - État de validation de l'inscription -
- getTrigram() . "\">" . $team->getName() . ""; - else - echo $team->getName(); - ?> - getTrigram() ?>getInscriptionDate()) ?>getValidationStatus()) ?>
- Équipe - - Trigramme - - Date d'inscription - - État de validation de l'inscription -
- - - - - diff --git a/server_files/views/profiles.php b/server_files/views/profiles.php deleted file mode 100644 index cc8f2e6..0000000 --- a/server_files/views/profiles.php +++ /dev/null @@ -1,63 +0,0 @@ - - -
-

-
- -
- Cette page recense tous les utilisateurs inscrits. -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - -
- Nom - - Rôle - - Inscrit le -
- getFirstName() . " " . $user->getSurname() ?>"> - getFirstName() . " " . $user->getSurname() ?> - - getRole()) ?>getInscriptionDate(), true) ?>
- Nom - - Rôle - - Inscrit le -
- - - -
-

Rejoindre une équipe

-
- - -
- Vous avez bien rejoint l'équipe getName() ?> ! -
-= $CONFIG->getInscriptionDate()) { ?> -
- La date limite d'inscription est dépassée. -
- - - 0) { ?> -
- Vous êtes déjà inscrit dans une équipe. Vous pouvez toutefois encadrer plusieurs équipes. -
- - -
-
-
- - -
-
- -
- -
-
- - - - \ No newline at end of file diff --git a/server_files/views/repondre_questions.php b/server_files/views/repondre_questions.php deleted file mode 100644 index ca578bc..0000000 --- a/server_files/views/repondre_questions.php +++ /dev/null @@ -1,93 +0,0 @@ - - -
-

Répondre aux questions

-
- - -
- Vos réponses ont bien été mises à jour ! -
- - -
- Deux autres équipes ayant travaillé sur le même problème que vous vous ont posé quelques questions. Afin de faire - avancer l'échange, vous êtes invités à répondre à leurs interrogations. Vous êtes libres d'ajouter à votre souhait - un paragraphe de remarques. -
- -
- Date limite de soumission des réponses : getEndPhase3Date(), true) ?> -
- -
- Lien de la vidéo : getLink() ?> -
- -getLink()); ?> - -getFrom()); - $remark = $questions_team[0]; - echo "

Questions de l'équipe " . $from->getName() . " (" . $from->getTrigram() . ") :

\n"; - if (!strcmp($questions_team[1]->getQuestion(), Question::DEFAULT_QUESTIONS[0]) - && !strcmp($questions_team[2]->getQuestion(), Question::DEFAULT_QUESTIONS[1]) - && !strcmp($questions_team[3]->getQuestion(), Question::DEFAULT_QUESTIONS[2])) { ?> -
- L'équipe n'a malheureusement transmis aucune question. Vous n'avez donc pas de réponse à donner. -
- -
- - - 0 && $question->getQuestion() == null) - continue; - ?> -
- getNumber() . " :" ?> - getQuestion() ?>
- getAttachedFile() != null) { ?> - Pièce jointe : - Télécharger
- -
-
- - -
-
- getAttachedFileAnswer() != null) { ?> - Pièce jointe : - Télécharger - -
-
- - -
-
-
- - - - -
-
- - - - - -
-

Suivi des Correspondances

-
- - 0) { ?> -
- pas encore - participé à la phase en cours : - pas encore participé à la phase en cours, ou leurs vidéos n'ont pas encore été validées : - - subject=Correspondances de Jeunes Mathématicien·ne·s" - target="_blank">Leur envoyer un mail -
- - -
- subject=Correspondances de Jeunes Mathématicien·ne·s" target="_blank"> - - - -
- - -
-

Vidéos pour le problème

-
- getLink(); - $team = Team::fromId($video->getTeam()); - $version = $video->getVersion(); - ?> -
-

- Équipe « getName() ?> » (getTrigram() ?>) -

-
- Lien de la vidéo (version ) : -
- getValidation() <= 0) { ?> -
- - - -
- - -
- - - getValidation() == 0) { ?> - - -
-
- getValidation() != 0) { ?> -
"> - La vidéo a été getValidation() == 1 ? "acceptée" : "refusée" ?>. -
- getValidation() != Video::ACCEPTED) { - $last_validated_video = Video::getVideo(Reason::SOLUTION, $team, Video::ACCEPTED); - if ($last_validated_video !== null) { - $link = $last_validated_video->getLink(); ?> -
- Lien de la vidéo validée de cette équipe (version ) : - -
- Phase::PHASE1) { - /** @var Question[] $from_questions */ - foreach (Question::getQuestionsTo($team) as $from_questions) { - - $from = Team::fromId($from_questions[0]->getFrom()); - echo "
Questions posées par l'équipe " . $from->getName() . " (" . $from->getTrigram() . ") :
\n"; - if (!strcmp($from_questions[1]->getQuestion(), Question::DEFAULT_QUESTIONS[0]) - && !strcmp($from_questions[2]->getQuestion(), Question::DEFAULT_QUESTIONS[1]) - && !strcmp($from_questions[3]->getQuestion(), Question::DEFAULT_QUESTIONS[2])) { ?> -
"> - Cette équipe n'a pas envoyé ses questions. -
- 0 && $question->getQuestion() == null) - continue; - - echo "
\n"; - echo "" . ($i == 0 ? "Remarques générales :" : "Question " . $i . " :") . " " . preg_replace("#\n#", "
\n", $question->getQuestion()) . "
\n"; - if ($question->getAttachedFile() != null) - echo "Pièce jointe attachée : getAttachedFile() . "\">Télécharger
\n"; - if ($question->getAnswer() != null) - echo "Réponse apportée : " . preg_replace("#\n#", "
\n", $question->getAnswer()) . "
\n"; - if ($question->getAttachedFileAnswer() != null) - echo "Pièce jointe attachée pour la réponse : getAttachedFileAnswer() . "\">Télécharger
\n"; - echo "
\n"; - } - echo "
\n"; - if (Phase::getCurrentPhase() >= Phase::PHASE4) { - $answer = Video::getVideo($from->getVideoTeamIds()[0] == $team->getId() ? Reason::ANSWER1 : Reason::ANSWER2, $from); - if ($answer == null) - continue; - $link = $answer->getLink(); - $version = $answer->getVersion(); - echo "
Vidéo de réponse :
\n"; - echo "Lien de la vidéo (version $version) : $link"; - displayVideo($link); - - if ($answer->getValidation() == 0) { ?> -
- - - -
- - -
- - - getValidation() == 0) { ?> - - -
-
- getValidation() != 0) { ?> -
"> - La vidéo a été getValidation() == 1 ? "acceptée" : "refusée" ?>. -
- getValidation() != Video::ACCEPTED) { - $last_validated_answer = Video::getVideo($from->getVideoTeamIds()[0] == $team->getId() ? Reason::ANSWER1 : Reason::ANSWER2, $team, Video::ACCEPTED); - if ($last_validated_answer !== null) { - $link = $last_validated_answer->getLink(); - echo "\n
\nLien de la dernière vidéo validée de cette équipe : $link
\n"; - displayVideo($link); - } - } - } - } - } - } ?> -
- \n"; -} - -require_once "footer.php"; \ No newline at end of file diff --git a/setup/create_database.sql b/setup/create_database.sql deleted file mode 100644 index 10aefe1..0000000 --- a/setup/create_database.sql +++ /dev/null @@ -1,146 +0,0 @@ --- phpMyAdmin SQL Dump --- version 4.7.5 --- https://www.phpmyadmin.net/ --- --- Hôte : db --- Généré le : mar. 22 oct. 2019 à 13:10 --- Version du serveur : 5.7.20 --- Version de PHP : 7.1.9 - -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -SET AUTOCOMMIT = 0; -START TRANSACTION; -SET time_zone = "+00:00"; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8mb4 */; - --- --- Base de données : `inscription_corres2math` --- - --- -------------------------------------------------------- - --- --- Structure de la table `config` --- - -CREATE TABLE IF NOT EXISTS `config` ( - `key` varchar(64) NOT NULL, - `value` varchar(8192) NOT NULL, - PRIMARY KEY (`key`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Structure de la table `documents` --- - -CREATE TABLE IF NOT EXISTS `documents` ( - `file_id` varchar(64) NOT NULL, - `user` int(11) NOT NULL, - `team` int(11) NOT NULL, - `problem` int(11) NOT NULL, - `uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`file_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Structure de la table `questions` --- - -CREATE TABLE IF NOT EXISTS `questions` ( - `id` int(8) NOT NULL AUTO_INCREMENT, - `from` int(8) NOT NULL, - `to` int(8) NOT NULL, - `problem` int(8) NOT NULL, - `number` int(8) NOT NULL, - `question` varchar(1024) DEFAULT NULL, - `attached_file` varchar(64) DEFAULT NULL, - `answer` varchar(1024) DEFAULT NULL, - `attached_file_answer` varchar(64) DEFAULT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Structure de la table `teams` --- - -CREATE TABLE IF NOT EXISTS `teams` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `name` varchar(64) NOT NULL, - `trigram` varchar(3) NOT NULL, - `problem` int(8) NOT NULL, - `encadrant` int(8) DEFAULT NULL, - `participant_1` int(8) DEFAULT NULL, - `participant_2` int(8) DEFAULT NULL, - `participant_3` int(8) DEFAULT NULL, - `participant_4` int(8) DEFAULT NULL, - `participant_5` int(8) DEFAULT NULL, - `inscription_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `allow_publish` tinyint(1) NOT NULL DEFAULT '0', - `validation_status` varchar(64) NOT NULL, - `video_team1` int(11) DEFAULT NULL, - `video_team2` int(11) DEFAULT NULL, - `access_code` varchar(6) NOT NULL, - `year` int(4) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Structure de la table `users` --- - -CREATE TABLE IF NOT EXISTS `users` ( - `id` int(8) NOT NULL AUTO_INCREMENT, - `email` varchar(255) NOT NULL, - `pwd_hash` varchar(64) NOT NULL, - `surname` varchar(255) NOT NULL, - `first_name` varchar(255) NOT NULL, - `school` varchar(255) DEFAULT NULL, - `city` varchar(256) DEFAULT NULL, - `country` varchar(256) DEFAULT NULL, - `class` varchar(255) DEFAULT NULL, - `description` varchar(255) DEFAULT NULL, - `role` varchar(64) NOT NULL, - `team_id` int(8) DEFAULT NULL, - `receive_animath_mails` tinyint(1) NOT NULL DEFAULT '0', - `year` int(4) NOT NULL DEFAULT '2020', - `confirm_email` varchar(64) DEFAULT NULL COMMENT 'Jeton de confirmation d''e-mail', - `forgotten_password` varchar(64) DEFAULT NULL COMMENT 'Jeton de récupération de mot de passe', - `inscription_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; - --- -------------------------------------------------------- - --- --- Structure de la table `videos` --- - -CREATE TABLE IF NOT EXISTS `videos` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `team` int(8) NOT NULL, - `problem` int(8) NOT NULL, - `link` varchar(128) NOT NULL, - `reason` varchar(64) NOT NULL, - `validation` tinyint(1) NOT NULL DEFAULT '0', - `uploaded_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, - `year` int(4) NOT NULL, - PRIMARY KEY (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8; -COMMIT; - -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/setup/msmtprc b/setup/msmtprc deleted file mode 100644 index 0be3f65..0000000 --- a/setup/msmtprc +++ /dev/null @@ -1,18 +0,0 @@ -defaults -auth on -tls on -tls_starttls off -tls_trust_file /etc/ssl/certs/ca-certificates.crt -syslog on -logfile /var/log/msmtp.log - -account corres2math -host ssl0.ovh.net -auth on -port 465 -from contact@correspondances-maths.fr -user contact@correspondances-maths.fr -passwordeval "echo $CORRES2MATH_MAIL_PASSWORD" - -# Set a default account -account default : corres2math diff --git a/templates/400.html b/templates/400.html new file mode 100644 index 0000000..0734a85 --- /dev/null +++ b/templates/400.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +

{% trans "Bad request" %}

+ {% blocktrans %}Sorry, your request was bad. Don't know what could be wrong. An email has been sent to webmasters with the details of the error. You can now watch some videos.{% endblocktrans %} +{% endblock %} \ No newline at end of file diff --git a/templates/403.html b/templates/403.html new file mode 100644 index 0000000..317865f --- /dev/null +++ b/templates/403.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +

{% trans "Permission denied" %}

+ {% blocktrans %}You don't have the right to perform this request.{% endblocktrans %} + {% if exception %} +
+ {% trans "Exception message:" %} {{ exception }} +
+ {% endif %} +{% endblock %} \ No newline at end of file diff --git a/templates/404.html b/templates/404.html new file mode 100644 index 0000000..8477f91 --- /dev/null +++ b/templates/404.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +

{% trans "Page not found" %}

+ {% blocktrans %}The requested path {{ request_path }} was not found on the server.{% endblocktrans %} + {% if exception != "Resolver404" %} +
+ {% trans "Exception message:" %} {{ exception }} +
+ {% endif %} +{% endblock %} \ No newline at end of file diff --git a/templates/500.html b/templates/500.html new file mode 100644 index 0000000..38d12e4 --- /dev/null +++ b/templates/500.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% load i18n %} + +{% block content %} +

{% trans "Server error" %}

+ {% blocktrans %}Sorry, an error occurred when processing your request. An email has been sent to webmasters with the detail of the error, and this will be fixed soon. You can now watch some videos.{% endblocktrans %} +{% endblock %} diff --git a/templates/amount_input.html b/templates/amount_input.html new file mode 100644 index 0000000..6ef4a53 --- /dev/null +++ b/templates/amount_input.html @@ -0,0 +1,11 @@ +
+ +
+ +
+
\ No newline at end of file diff --git a/templates/autocomplete_model.html b/templates/autocomplete_model.html new file mode 100644 index 0000000..2236c6e --- /dev/null +++ b/templates/autocomplete_model.html @@ -0,0 +1,9 @@ + + +
    +
diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..eceb437 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,154 @@ +{% load static i18n static %} + + + + + + + + {% block title %}{{ title }}{% endblock title %} - Plateforme des Correspondances + + + + {# Favicon #} + + + {% if no_cache %} + + {% endif %} + + {# Bootstrap CSS #} + + + + + {# JQuery, Bootstrap and Turbolinks JavaScript #} + + + + + + {# Si un formulaire requiert des données supplémentaires (notamment JS), les données sont chargées #} + {% if form.media %} + {{ form.media }} + {% endif %} + + + + {% block extracss %}{% endblock %} + + +
+ +
+ {% block contenttitle %}

{{ title }}

{% endblock %} +
+ {% block content %} +

Default content...

+ {% endblock content %} +
+
+ +
+
+
+
+
+ + — + {% trans "Contact us" %} — + + {% csrf_token %} + + +
+
+ +
+
+
+ + + +{% block extrajavascript %} +{% endblock extrajavascript %} + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..8272782 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} + +{% block content %} + {% autoescape off %} + {% endautoescape %} +{% endblock %} diff --git a/templates/registration/email_validation_complete.html b/templates/registration/email_validation_complete.html new file mode 100644 index 0000000..f58a7e5 --- /dev/null +++ b/templates/registration/email_validation_complete.html @@ -0,0 +1,27 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +
+

+ {{ title }} +

+
+ {% if validlink %} +

+ {% trans "Your email have successfully been validated." %} +

+

+ {% blocktrans %}You can now log in.{% endblocktrans %} +

+ {% else %} +

+ {% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %} +

+ {% endif %} +
+
+{% endblock %} diff --git a/templates/registration/email_validation_email_sent.html b/templates/registration/email_validation_email_sent.html new file mode 100644 index 0000000..adc0c02 --- /dev/null +++ b/templates/registration/email_validation_email_sent.html @@ -0,0 +1,18 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +
+

+ {% trans "Account activation" %} +

+
+

+ {% trans "An email has been sent. Please click on the link to activate your account." %} +

+
+
+{% endblock %} diff --git a/templates/registration/logged_out.html b/templates/registration/logged_out.html new file mode 100644 index 0000000..3b044b7 --- /dev/null +++ b/templates/registration/logged_out.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "Thanks for spending some quality time with the Web site today." %}

+

{% trans 'Log in again' %}

+{% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..64c5c26 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-2.0-or-later +{% endcomment %} +{% load i18n crispy_forms_filters %} + +{% block title %}{% trans "Log in" %}{% endblock %} +{% block contenttitle %}

{% trans "Log in" %}

{% endblock %} + +{% block content %} + {% if user.is_authenticated %} +

+ {% blocktrans trimmed %} + You are authenticated as {{ user }}, but are not authorized to + access this page. Would you like to login to a different account? + {% endblocktrans %} +

+ {% endif %} +
+ {% csrf_token %} + {{ form | crispy }} + + {% trans 'Forgotten your password or username?' %} +
+{% endblock %} diff --git a/templates/registration/mails/email_validation_email.html b/templates/registration/mails/email_validation_email.html new file mode 100644 index 0000000..cd0bfed --- /dev/null +++ b/templates/registration/mails/email_validation_email.html @@ -0,0 +1,36 @@ +{% load i18n %} + + + + + + + + + +

+ {% trans "Hi" %} {{ user.username }}, +

+ +

+ {% trans "You recently registered on the Correspondances platform. Please click on the link below to confirm your registration." %} +

+ +

+ + https://{{ domain }}{% url 'member:email_validation' uidb64=uid token=token %} + +

+ +

+ {% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %} +

+ +

+ {% trans "Thanks" %}, +

+ +-- +

+ {% trans "The CNO." %}
+

diff --git a/templates/registration/mails/email_validation_email.txt b/templates/registration/mails/email_validation_email.txt new file mode 100644 index 0000000..b12d3fa --- /dev/null +++ b/templates/registration/mails/email_validation_email.txt @@ -0,0 +1,13 @@ +{% load i18n %} + +{% trans "Hi" %} {{ user.username }}, + +{% trans "You recently registered on the Correspondances platform. Please click on the link below to confirm your registration." %} + +https://{{ domain }}{% url 'member:email_validation' uidb64=uid token=token %} + +{% trans "This link is only valid for a couple of days, after that you will need to contact us to validate your email." %} + +{% trans "Thanks" %}, + +{% trans "The CNO." %} diff --git a/templates/registration/password_change_done.html b/templates/registration/password_change_done.html new file mode 100644 index 0000000..150a00e --- /dev/null +++ b/templates/registration/password_change_done.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans 'Your password was changed.' %}

+{% endblock %} diff --git a/templates/registration/password_change_form.html b/templates/registration/password_change_form.html new file mode 100644 index 0000000..01133e4 --- /dev/null +++ b/templates/registration/password_change_form.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} +
{% csrf_token %} +

{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}

+ {{ form | crispy }} + +
+{% endblock %} \ No newline at end of file diff --git a/templates/registration/password_reset_complete.html b/templates/registration/password_reset_complete.html new file mode 100644 index 0000000..dec34f6 --- /dev/null +++ b/templates/registration/password_reset_complete.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "Your password has been set. You may go ahead and log in now." %}

+

+ {% trans 'Log in' %} +

+{% endblock %} diff --git a/templates/registration/password_reset_confirm.html b/templates/registration/password_reset_confirm.html new file mode 100644 index 0000000..6432872 --- /dev/null +++ b/templates/registration/password_reset_confirm.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} + {% if validlink %} +

{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}

+
{% csrf_token %} + {{ form | crispy }} + +
+ {% else %} +

{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}

+ {% endif %} +{% endblock %} diff --git a/templates/registration/password_reset_done.html b/templates/registration/password_reset_done.html new file mode 100644 index 0000000..a215ab9 --- /dev/null +++ b/templates/registration/password_reset_done.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." %}

+

{% trans "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." %}

+{% endblock %} diff --git a/templates/registration/password_reset_form.html b/templates/registration/password_reset_form.html new file mode 100644 index 0000000..61adaa9 --- /dev/null +++ b/templates/registration/password_reset_form.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} +

{% trans "Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one." %}

+
{% csrf_token %} + {{ form | crispy }} + +
+{% endblock %} diff --git a/templates/registration/signup.html b/templates/registration/signup.html new file mode 100644 index 0000000..ed100d0 --- /dev/null +++ b/templates/registration/signup.html @@ -0,0 +1,17 @@ + +{% extends 'base.html' %} +{% load crispy_forms_filters %} +{% load i18n %} +{% block title %}{% trans "Sign up" %}{% endblock %} + +{% block content %} +

{% trans "Sign up" %}

+ +
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock %}