From fa5202fe4f608fc455a7c638cba8103497e5067d Mon Sep 17 00:00:00 2001 From: galaxyoyo Date: Tue, 10 Sep 2019 01:48:52 +0200 Subject: [PATCH] =?UTF-8?q?Copie=20du=20site=20du=20TFJM=C2=B2=20=C3=A0=20?= =?UTF-8?q?adapter=20aux=20Correspondances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .htaccess | 7 + .idea/.gitignore | 3 + .idea/Correspondances.iml | 8 + .idea/deployment.xml | 15 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + .idea/webServers.xml | 15 + Dockerfile | 37 ++ assets/favicon.ico | Bin 0 -> 1514 bytes assets/logo.svg | 114 +++++ assets/style.css | 80 ++++ dispatcher.php | 76 ++++ index.html | 12 + server_files/403.php | 12 + server_files/404.php | 12 + server_files/classes/Document.php | 318 ++++++++++++++ server_files/classes/Role.php | 48 +++ server_files/classes/SchoolClass.php | 41 ++ server_files/classes/Team.php | 185 +++++++++ server_files/classes/Tournament.php | 357 ++++++++++++++++ server_files/classes/User.php | 391 ++++++++++++++++++ server_files/classes/ValidationStatus.php | 41 ++ server_files/config.php | 28 ++ server_files/controllers/ajouter_equipe.php | 63 +++ .../controllers/ajouter_organisateur.php | 57 +++ server_files/controllers/ajouter_tournoi.php | 104 +++++ server_files/controllers/confirmer_mail.php | 19 + server_files/controllers/connexion.php | 170 ++++++++ server_files/controllers/deconnexion.php | 8 + server_files/controllers/equipe.php | 57 +++ server_files/controllers/index.php | 3 + server_files/controllers/informations.php | 26 ++ server_files/controllers/inscription.php | 93 +++++ server_files/controllers/mon_compte.php | 152 +++++++ server_files/controllers/mon_equipe.php | 141 +++++++ server_files/controllers/rejoindre_equipe.php | 66 +++ server_files/controllers/solutions.php | 72 ++++ server_files/controllers/solutions_orga.php | 24 ++ server_files/controllers/syntheses.php | 68 +++ server_files/controllers/syntheses_orga.php | 22 + server_files/controllers/tournoi.php | 125 ++++++ server_files/controllers/tournois.php | 5 + server_files/controllers/view_file.php | 78 ++++ server_files/model.php | 251 +++++++++++ server_files/services/mail.php | 130 ++++++ .../mail_templates/add_organizer.html | 21 + .../add_organizer_for_tournament.html | 17 + .../services/mail_templates/add_team.html | 16 + .../mail_templates/change_email_address.html | 16 + .../mail_templates/change_password.html | 18 + .../mail_templates/confirm_email.html | 18 + .../mail_templates/forgotten_password.html | 20 + .../services/mail_templates/join_team.html | 17 + .../services/mail_templates/register.html | 16 + server_files/utils.php | 32 ++ server_files/views/ajouter_equipe.php | 56 +++ server_files/views/ajouter_organisateur.php | 57 +++ server_files/views/ajouter_tournoi.php | 127 ++++++ server_files/views/connexion.php | 100 +++++ server_files/views/equipe.php | 63 +++ server_files/views/footer.php | 6 + server_files/views/header.php | 76 ++++ server_files/views/index.php | 127 ++++++ server_files/views/informations.php | 44 ++ server_files/views/inscription.php | 178 ++++++++ server_files/views/mon_compte.php | 178 ++++++++ server_files/views/mon_equipe.php | 161 ++++++++ server_files/views/rejoindre_equipe.php | 33 ++ server_files/views/solutions.php | 75 ++++ server_files/views/solutions_orga.php | 25 ++ server_files/views/syntheses.php | 79 ++++ server_files/views/syntheses_orga.php | 27 ++ server_files/views/tournoi.php | 220 ++++++++++ server_files/views/tournois.php | 41 ++ setup/create_database.sql | 184 +++++++++ setup/msmtprc | 18 + 77 files changed, 5620 insertions(+) create mode 100644 .htaccess create mode 100644 .idea/.gitignore create mode 100644 .idea/Correspondances.iml create mode 100644 .idea/deployment.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/webServers.xml create mode 100644 Dockerfile create mode 100644 assets/favicon.ico create mode 100644 assets/logo.svg create mode 100644 assets/style.css create mode 100644 dispatcher.php create mode 100644 index.html create mode 100644 server_files/403.php create mode 100644 server_files/404.php create mode 100644 server_files/classes/Document.php create mode 100644 server_files/classes/Role.php create mode 100644 server_files/classes/SchoolClass.php create mode 100644 server_files/classes/Team.php create mode 100644 server_files/classes/Tournament.php create mode 100644 server_files/classes/User.php create mode 100644 server_files/classes/ValidationStatus.php create mode 100644 server_files/config.php create mode 100644 server_files/controllers/ajouter_equipe.php create mode 100644 server_files/controllers/ajouter_organisateur.php create mode 100644 server_files/controllers/ajouter_tournoi.php create mode 100644 server_files/controllers/confirmer_mail.php create mode 100644 server_files/controllers/connexion.php create mode 100644 server_files/controllers/deconnexion.php create mode 100644 server_files/controllers/equipe.php create mode 100644 server_files/controllers/index.php create mode 100644 server_files/controllers/informations.php create mode 100644 server_files/controllers/inscription.php create mode 100644 server_files/controllers/mon_compte.php create mode 100644 server_files/controllers/mon_equipe.php create mode 100644 server_files/controllers/rejoindre_equipe.php create mode 100644 server_files/controllers/solutions.php create mode 100644 server_files/controllers/solutions_orga.php create mode 100644 server_files/controllers/syntheses.php create mode 100644 server_files/controllers/syntheses_orga.php create mode 100644 server_files/controllers/tournoi.php create mode 100644 server_files/controllers/tournois.php create mode 100644 server_files/controllers/view_file.php create mode 100644 server_files/model.php create mode 100644 server_files/services/mail.php create mode 100644 server_files/services/mail_templates/add_organizer.html create mode 100644 server_files/services/mail_templates/add_organizer_for_tournament.html create mode 100644 server_files/services/mail_templates/add_team.html create mode 100644 server_files/services/mail_templates/change_email_address.html create mode 100644 server_files/services/mail_templates/change_password.html create mode 100644 server_files/services/mail_templates/confirm_email.html create mode 100644 server_files/services/mail_templates/forgotten_password.html create mode 100644 server_files/services/mail_templates/join_team.html create mode 100644 server_files/services/mail_templates/register.html create mode 100644 server_files/utils.php create mode 100644 server_files/views/ajouter_equipe.php create mode 100644 server_files/views/ajouter_organisateur.php create mode 100644 server_files/views/ajouter_tournoi.php create mode 100644 server_files/views/connexion.php create mode 100644 server_files/views/equipe.php create mode 100644 server_files/views/footer.php create mode 100644 server_files/views/header.php create mode 100644 server_files/views/index.php create mode 100644 server_files/views/informations.php create mode 100644 server_files/views/inscription.php create mode 100644 server_files/views/mon_compte.php create mode 100644 server_files/views/mon_equipe.php create mode 100644 server_files/views/rejoindre_equipe.php create mode 100644 server_files/views/solutions.php create mode 100644 server_files/views/solutions_orga.php create mode 100644 server_files/views/syntheses.php create mode 100644 server_files/views/syntheses_orga.php create mode 100644 server_files/views/tournoi.php create mode 100644 server_files/views/tournois.php create mode 100644 setup/create_database.sql create mode 100644 setup/msmtprc diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..12806a1 --- /dev/null +++ b/.htaccess @@ -0,0 +1,7 @@ +ErrorDocument 403 /tfjm/server_files/403.php +ErrorDocument 404 /tfjm/server_files/404.php + +Options +FollowSymlinks +Options -Indexes +RewriteEngine On +RewriteRule ^(.*)$ dispatcher.php?path=$1 [QSA,L] diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..0e40fe8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ + +# Default ignored files +/workspace.xml \ No newline at end of file diff --git a/.idea/Correspondances.iml b/.idea/Correspondances.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/Correspondances.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/deployment.xml b/.idea/deployment.xml new file mode 100644 index 0000000..cf50945 --- /dev/null +++ b/.idea/deployment.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..a80396f --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/webServers.xml b/.idea/webServers.xml new file mode 100644 index 0000000..752c344 --- /dev/null +++ b/.idea/webServers.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..40f91da --- /dev/null +++ b/Dockerfile @@ -0,0 +1,37 @@ +FROM php:7.3-apache as plateforme-builder + +# Enabling apache rewrite mod +RUN a2enmod rewrite + +RUN apt clean && apt update && apt upgrade -y + +# Install MySQL drivers +RUN docker-php-ext-install pdo_mysql \ + && docker-php-ext-enable pdo_mysql + +# 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 + +# 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 + +# Setup timezone +RUN echo Europe/Paris > /etc/timezone \ + && ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime \ + && dpkg-reconfigure -f noninteractive tzdata + +# 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 + +# Setting environment +ENV TFJM_LOCAL_PATH /var/www/html +ENV TFJM_MAIL_DOMAIN tfjm.org +ENV TFJM_URL_BASE https://inscription.correspondances-maths.fr diff --git a/assets/favicon.ico b/assets/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..97757d37b247a0f247f1288a6f1a43c15614b612 GIT binary patch literal 1514 zcmcgsO-o{76uz^V)$C^-%w|^elllR+Y!L+NV1Ypz^nr>Lq*i7YrIls*QEDbGl+vhF zGzcTgJ~l}o)-yh5xFX@i%w~?f-uIsOyyrRRIp7_s3MiFIczSxm%gYPO<+A8bPEK%faY0j&bUKax z{(kiJ^lR4NtG6XWXYN_EqEW-=KVjYje1a=GyE z@PNn1M{qwnIx1(hd3$@4I|~a7Fq_Tr`~8@moyG3%E{H`Rdc7X^_xGZs9rJKF9OB1d zFo1sE3-euBS;6-9Hja;vTgQiohX@1$SY2Jk>+7p59^TyC;Qag?$z&3dNJMO?XB>Pd z=G@#I#>U3Pmb|R5uL}mx-pilxbGe-O=3Vke-zo?6LHuYm+QLsH5{SiOQp2UCCFpcI zxx+fHt*yc5^GR&~g1@n`A$1uX9F%AK-A?#BJ39ylgIHW#l(?p+r@=g!LnnOZ^HKi9 zpPHJ2#bOaYKf>SJ+k@BZ1#|a!Jkkf;FE1~HepGzcV}E~N_>0Hm(yMCy+3U4hP5LCC z&$sx$zP<)?V=mlN=%bx~^1&V?-qzNZ*l?x>1_oOEa~{}FJv}`b9v((_cQ;b06r4_{ z+zW@pn3$M=-ENoo$Rm54F=ew^^!E13ERi?%ChIysKQA0|9yA(_^xoOonc%bEv|24} zHXB%rySqD?N%l!76q0yHMn;5RVsf5`hK8hX$RTxBs}*jyTli;B(?_*h#pL9qEc!k; zIFKAnCX?jOJXK-b^g-XW<1BH$Syxqz>*lK0KcP5FkY-{HS`{sP(p$%_C0 literal 0 HcmV?d00001 diff --git a/assets/logo.svg b/assets/logo.svg new file mode 100644 index 0000000..699316b --- /dev/null +++ b/assets/logo.svg @@ -0,0 +1,114 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/assets/style.css b/assets/style.css new file mode 100644 index 0000000..bf10db5 --- /dev/null +++ b/assets/style.css @@ -0,0 +1,80 @@ +body { + display: flex; +} + +html, body { + height: 100%; + width: 100%; + margin: 0; +} + +#menu { + list-style-type: none; + margin: 0; + padding: 0; + width: 220px; + background-color: #f1f1f1; + height: 100%; + overflow: auto; + flex-grow: 0; +} + +#menu a { + display: block; + color: #000; + padding: 10px 20px; + text-decoration: none; +} + +#menu a.active { + background-color: #4CAF50; + color: white; +} + +#menu a:hover:not(.active) { + background-color: #555; + color: white; +} + +#menu-logo img { + width: calc(100% - 40px); + margin: 40px auto; + display: block; +} + +#main-container { + margin: 0; + flex-grow: 1; + height: 100%; + overflow-y: scroll; +} + +#main-content { + padding-top: 100px; + padding-bottom: 100px; + margin: 0 auto; + max-width: 1000px; + text-align: justify; +} + +@media only screen and (max-width: 700px) { + body { + flex-direction: column; + height: auto; + } + #menu { + height: auto; + width: 100%; + padding-bottom: 20px; + } + #menu-logo img { + height: 70px; + padding-left: 7px; + } + #menu a { + text-align: center; + } + #main-content { + padding: 100px 16px; + } +} diff --git a/dispatcher.php b/dispatcher.php new file mode 100644 index 0000000..23abe0a --- /dev/null +++ b/dispatcher.php @@ -0,0 +1,76 @@ + $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/index.html b/index.html new file mode 100644 index 0000000..da8c197 --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + Erreur + + + +Le mode Rewrite n'est pas activé. + + \ No newline at end of file diff --git a/server_files/403.php b/server_files/403.php new file mode 100644 index 0000000..51e6852 --- /dev/null +++ b/server_files/403.php @@ -0,0 +1,12 @@ +Vous n'êtes pas autorisé à accéder à cette page."; + +require_once "views/footer.php"; + +exit(); \ No newline at end of file diff --git a/server_files/404.php b/server_files/404.php new file mode 100644 index 0000000..9fc419b --- /dev/null +++ b/server_files/404.php @@ -0,0 +1,12 @@ +Cette page n'existe pas."; + +require_once "views/footer.php"; + +exit(); \ No newline at end of file diff --git a/server_files/classes/Document.php b/server_files/classes/Document.php new file mode 100644 index 0000000..020eeab --- /dev/null +++ b/server_files/classes/Document.php @@ -0,0 +1,318 @@ +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->tournament_id = $data["tournament"]; + $this->type = DocumentType::fromName($data["type"]); + $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 getTournamentId() + { + return $this->tournament_id; + } + + public function getType() + { + return $this->type; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class Solution +{ + private $file_id; + private $team_id; + private $tournament_id; + private $problem; + private $uploaded_at; + private $version; + + private function __construct() {} + + public static function fromId($id) + { + global $DB; + $req = $DB->prepare("SELECT * FROM `solutions` WHERE `file_id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + return self::fromData($data); + } + + public static function fromData($data) + { + $sol = new Solution(); + $sol->fill($data); + return $sol; + } + + private function fill($data) + { + $this->file_id = $data["file_id"]; + $this->team_id = $data["team"]; + $this->tournament_id = $data["tournament"]; + $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 getTeamId() + { + return $this->team_id; + } + + public function getTournamentId() + { + return $this->tournament_id; + } + + public function getProblem() + { + return $this->problem; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class Synthesis +{ + private $file_id; + private $team_id; + private $tournament_id; + private $dest; + private $uploaded_at; + private $version; + + private function __construct() {} + + public static function fromId($id) + { + global $DB; + $req = $DB->prepare("SELECT * FROM `syntheses` WHERE `file_id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + return self::fromData($data); + } + + public static function fromData($data) + { + $synthese = new Synthesis(); + $synthese->fill($data); + return $synthese; + } + + private function fill($data) + { + $this->file_id = $data["file_id"]; + $this->team_id = $data["team"]; + $this->tournament_id = $data["tournament"]; + $this->dest = DestType::fromName($data["dest"]); + $this->uploaded_at = $data["uploaded_at"]; + $this->version = isset($data["version"]) ? $data["version"] : 1; + } + + public function getFileId() + { + return $this->file_id; + } + + public function getTeamId() + { + return $this->team_id; + } + + public function getTournamentId() + { + return $this->tournament_id; + } + + public function getDest() + { + return $this->dest; + } + + public function getUploadedAt() + { + return $this->uploaded_at; + } + + public function getVersion() + { + return $this->version; + } +} + +class DestType +{ + const DEFENSEUR = 0; + const OPPOSANT = 1; + const RAPPORTEUR = 2; + + public static function getTranslatedName($status) { + switch ($status) { + case self::OPPOSANT: + return "Opposant"; + case self::RAPPORTEUR: + return "Rapporteur"; + default: + return "Défenseur"; + } + } + + public static function getName($status) { + switch ($status) { + case self::OPPOSANT: + return "OPPOSANT"; + case self::RAPPORTEUR: + return "RAPPORTEUR"; + default: + return "DEFENSEUR"; + } + } + + public static function fromName($name) { + switch ($name) { + case "OPPOSANT": + return self::OPPOSANT; + case "RAPPORTEUR": + return self::RAPPORTEUR; + default: + return self::DEFENSEUR; + } + } +} + +class DocumentType +{ + const PARENTAL_CONSENT = 0; + const PHOTO_CONSENT = 1; + const SANITARY_PLUG = 2; + const SOLUTION = 3; + const SYNTHESIS = 4; + + public static function getTranslatedName($type) { + switch ($type) { + case self::PARENTAL_CONSENT: + return "Autorisation parentale"; + case self::PHOTO_CONSENT: + return "Autorisation de droit à l'image"; + case self::SANITARY_PLUG: + return "Fiche sanitaire"; + case self::SOLUTION: + return "Solution"; + default: + return "Note de synthèse"; + } + } + + public static function getName($type) { + switch ($type) { + case self::PARENTAL_CONSENT: + return "PARENTAL_CONSENT"; + case self::PHOTO_CONSENT: + return "PHOTO_CONSENT"; + case self::SANITARY_PLUG: + return "SANITARY_PLUG"; + case self::SOLUTION: + return "SOLUTION"; + default: + return "SYNTHESIS"; + } + } + + public static function fromName($name) { + switch ($name) { + case "PARENTAL_CONSENT": + return self::PARENTAL_CONSENT; + case "PHOTO_CONSENT": + return self::PHOTO_CONSENT; + case "SANITARY_PLUG": + return self::SANITARY_PLUG; + case "SOLUTION": + return self::SOLUTION; + default: + return self::SYNTHESIS; + } + } +} \ No newline at end of file diff --git a/server_files/classes/Role.php b/server_files/classes/Role.php new file mode 100644 index 0000000..5fa557a --- /dev/null +++ b/server_files/classes/Role.php @@ -0,0 +1,48 @@ +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; + } + + 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; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->name = $data["name"]; + $this->trigram = $data["trigram"]; + $this->tournament = $data["tournament"]; + $this->encadrants = [$data["encadrant_1"], $data["encadrant_2"]]; + $this->participants = [$data["participant_1"], $data["participant_2"], $data["participant_3"], $data["participant_4"], $data["participant_5"], $data["participant_6"]]; + $this->inscription_date = $data["inscription_date"]; + $this->validation_status = ValidationStatus::fromName($data["validation_status"]); + $this->final_selection = $data["final_selection"] == true; + $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 getTournamentId() + { + return $this->tournament; + } + + public function setTournamentId($tournament) + { + global $DB; + $this->tournament = $tournament; + $DB->prepare("UPDATE `teams` SET `tournament` = ? WHERE `id` = ?;")->execute([$tournament, $this->id]); + } + + public function getEncadrants() + { + return $this->encadrants; + } + + public function setEncadrant($i, $encadrant) + { + global $DB; + $this->encadrants[$i - 1] = $encadrant; + /** @noinspection SqlResolve */ + $DB->prepare("UPDATE `teams` SET `encadrant_$i` = ? 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 getValidationStatus() + { + return $this->validation_status; + } + + public function setValidationStatus($status) + { + global $DB; + $this->validation_status = $status; + /** @noinspection PhpUndefinedMethodInspection */ + $DB->prepare("UPDATE `teams` SET `validation_status` = ? WHERE `id` = ?;")->execute([ValidationStatus::getName($status), $this->id]); + } + + public function isSelectedForFinal() + { + return $this->final_selection; + } + + public function selectForFinal($selected) + { + global $DB; + $this->final_selection = $selected; + $DB->prepare("UPDATE `teams` SET `final_selection` = ? WHERE `id` = ?;")->execute([$selected, $this->id]); + } + + public function getAccessCode() + { + return $this->access_code; + } + + public function getYear() + { + return $this->year; + } +} diff --git a/server_files/classes/Tournament.php b/server_files/classes/Tournament.php new file mode 100644 index 0000000..e404e7d --- /dev/null +++ b/server_files/classes/Tournament.php @@ -0,0 +1,357 @@ +prepare("SELECT * FROM `tournaments` WHERE `id` = ?;"); + $req->execute([htmlspecialchars($id)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function fromName($name) + { + global $DB, $YEAR; + $req = $DB->prepare("SELECT * FROM `tournaments` WHERE `name` = ? AND `year` = $YEAR;"); + $req->execute([htmlspecialchars($name)]); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function getFinalTournament() + { + global $DB, $YEAR; + $req = $DB->query("SELECT * FROM `tournaments` WHERE `final` AND `year` = $YEAR;"); + $data = $req->fetch(); + + if ($data === false) + return null; + + $tournament = new Tournament(); + $tournament->fill($data); + return $tournament; + } + + public static function getAllTournaments($include_final = true, $only_future = false) + { + global $DB, $YEAR; + $sql = "SELECT * FROM `tournaments` WHERE "; + if (!$include_final) + $sql .= "`final` = 0 AND "; + if ($only_future) + $sql .= "`date_start` > CURRENT_DATE AND "; + $sql .= "`year` = $YEAR ORDER BY `date_start`, `name`;"; + $req = $DB->query($sql); + + $tournaments = []; + + while (($data = $req->fetch()) !== false) { + $tournament = new Tournament(); + $tournament->fill($data); + $tournaments[] = $tournament; + } + + return $tournaments; + } + + private function fill($data) + { + $this->id = $data["id"]; + $this->name = $data["name"]; + $this->size = $data["size"]; + $this->place = $data["place"]; + $this->price = $data["price"]; + $this->description = $data["description"]; + $this->date_start = $data["date_start"]; + $this->date_end = $data["date_end"]; + $this->date_inscription = $data["date_inscription"]; + $this->date_solutions = $data["date_solutions"]; + $this->date_syntheses = $data["date_syntheses"]; + $this->final = $data["final"] == true; + $this->year = $data["year"]; + + global $DB; + $req = $DB->prepare("SELECT `organizer` FROM `organizers` WHERE `tournament` = ?;"); + $req->execute([$this->id]); + + while (($data = $req->fetch()) !== false) + $this->organizers[] = User::fromId($data["organizer"]); + } + + public function getId() + { + return $this->id; + } + + public function getName() + { + return $this->name; + } + + public function setName($name) + { + global $DB; + $this->name = $name; + $DB->prepare("UPDATE `tournaments` SET `name` = ? WHERE `id` = ?;")->execute([$name, $this->id]); + } + + public function getSize() + { + return $this->size; + } + + public function setSize($size) + { + global $DB; + $this->size = $size; + $DB->prepare("UPDATE `tournaments` SET `size` = ? WHERE `id` = ?;")->execute([$size, $this->id]); + } + + public function getPlace() + { + return $this->place; + } + + public function setPlace($place) + { + global $DB; + $this->place = $place; + $DB->prepare("UPDATE `tournaments` SET `place` = ? WHERE `id` = ?;")->execute([$place, $this->id]); + } + + public function getPrice() + { + return $this->price; + } + + public function setPrice($price) + { + global $DB; + $this->price = $price; + $DB->prepare("UPDATE `tournaments` SET `price` = ? WHERE `id` = ?;")->execute([$price, $this->id]); + } + + public function getDescription() + { + return $this->description; + } + + public function setDescription($desc) + { + global $DB; + $this->description = $desc; + $DB->prepare("UPDATE `tournaments` SET `description` = ? WHERE `id` = ?;")->execute([$desc, $this->id]); + } + + public function getStartDate() + { + return $this->date_start; + } + + public function setStartDate($date) + { + global $DB; + $this->date_start = $date; + $DB->prepare("UPDATE `tournaments` SET `date_start` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getEndDate() + { + return $this->date_end; + } + + public function setEndDate($date) + { + global $DB; + $this->date_end = $date; + $DB->prepare("UPDATE `tournaments` SET `date_end` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getInscriptionDate() + { + return $this->date_inscription; + } + + public function setInscriptionDate($date) + { + global $DB; + $this->date_inscription = $date; + $DB->prepare("UPDATE `tournaments` SET `date_inscription` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSolutionsDate() + { + return $this->date_solutions; + } + + public function setSolutionsDate($date) + { + global $DB; + $this->date_solutions = $date; + $DB->prepare("UPDATE `tournaments` SET `date_solutions` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function getSynthesesDate() + { + return $this->date_syntheses; + } + + public function setSynthesesDate($date) + { + global $DB; + $this->date_syntheses = $date; + $DB->prepare("UPDATE `tournaments` SET `date_syntheses` = ? WHERE `id` = ?;")->execute([$date, $this->id]); + } + + public function isFinal() + { + return $this->final; + } + + public function setFinal($final) + { + global $DB; + $this->final = $final; + $DB->prepare("UPDATE `tournaments` SET `final` = ? WHERE `id` = ?;")->execute([$final, $this->id]); + } + + public function getAllTeams() + { + global $DB, $YEAR; + if ($this->final) + $req = $DB->query("SELECT `id` FROM `teams` WHERE `final_selection` AND `year` = $YEAR;"); + else + $req = $DB->query("SELECT `id` FROM `teams` WHERE `tournament` = $this->id AND `year` = $YEAR;"); + + $teams = []; + + while (($data = $req->fetch()) !== false) + $teams[] = Team::fromId($data["id"]); + + return $teams; + } + + public function getOrganizers() + { + return $this->organizers; + } + + public function organize($user_id) + { + foreach ($this->organizers as $organizer) { + if ($organizer->getId() == $user_id) + return true; + } + + return false; + } + + public function addOrganizer(User $user) + { + global $DB; + + $this->organizers[] = $user; + + $req = $DB->prepare("INSERT INTO `organizers`(`organizer`, `tournament`) VALUES(?, ?);"); + $req->execute([$user->getId(), $this->id]); + } + + public function clearOrganizers() + { + global $DB; + + $this->organizers = []; + + $req = $DB->prepare("DELETE FROM `organizers` WHERE `tournament` = ?;"); + $req->execute([$this->id]); + } + + public function getYear() + { + return $this->year; + } + + public function getAllDocuments($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `documents` AS `t1` " + . "INNER JOIN (SELECT `user`, `type`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `tournament`, `team`, `type`, `user`) `t2` " + . "ON `t1`.`user` = `t2`.`user` AND `t1`.`type` = `t2`.`type` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`type`;"); + + $docs = []; + + while (($data = $req->fetch()) !== false) + $docs[] = Document::fromData($data); + + return $docs; + } + + public function getAllSolutions($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `solutions` AS `t1` " + . "INNER JOIN (SELECT `team`, `problem`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `solutions` GROUP BY `tournament`, `team`, `problem`) `t2` " + . "ON `t1`.`team` = `t2`.`team` AND `t1`.`problem` = `t2`.`problem` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`problem`;"); + + $sols = []; + + while (($data = $req->fetch()) !== false) + $sols[] = Solution::fromData($data); + + return $sols; + } + + public function getAllSyntheses($team_id = -1) + { + global $DB; + + $req = $DB->query("SELECT * FROM `syntheses` AS `t1` " + . "INNER JOIN (SELECT `team`, `dest`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `syntheses` GROUP BY `tournament`, `team`, `dest`) `t2` " + . "ON `t1`.`team` = `t2`.`team` AND `t1`.`dest` = `t2`.`dest` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $this->id " . ($team_id == -1 ? "" : "AND `t1`.`team` = $team_id") . " ORDER BY `t1`.`team`, `t1`.`dest`;"); + + $syntheses = []; + + while (($data = $req->fetch()) !== false) + $syntheses[] = Synthesis::fromData($data); + + return $syntheses; + } +} \ No newline at end of file diff --git a/server_files/classes/User.php b/server_files/classes/User.php new file mode 100644 index 0000000..cd1fd8d --- /dev/null +++ b/server_files/classes/User.php @@ -0,0 +1,391 @@ +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; + } + + 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->birth_date = $data["birth_date"]; + $this->gender = $data["gender"]; + $this->address = $data["address"]; + $this->postal_code = $data["postal_code"]; + $this->city = $data["city"]; + $this->country = $data["country"]; + $this->phone_number = $data["phone_number"]; + $this->school = $data["school"]; + $this->class = SchoolClass::fromName($data["class"]); + $this->responsible_name = $data["responsible_name"]; + $this->responsible_phone = $data["responsible_phone"]; + $this->responsible_email = $data["responsible_email"]; + $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"]; + } + + 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 getBirthDate() + { + return $this->birth_date; + } + + public function setBirthDate($birth_date) + { + global $DB; + $this->birth_date = $birth_date; + $DB->prepare("UPDATE `users` SET `birth_date` = ? WHERE `id` = ?;")->execute([$birth_date, $this->getId()]); + } + + public function getGender() + { + return $this->gender; + } + + public function setGender($gender) + { + global $DB; + $this->gender = $gender; + $DB->prepare("UPDATE `users` SET `gender` = ? WHERE `id` = ?;")->execute([$gender, $this->getId()]); + } + + public function getAddress() + { + return $this->address; + } + + public function setAddress($address) + { + global $DB; + $this->address = $address; + $DB->prepare("UPDATE `users` SET `address` = ? WHERE `id` = ?;")->execute([$address, $this->getId()]); + } + + public function getPostalCode() + { + return $this->postal_code; + } + + public function setPostalCode($postal_code) + { + global $DB; + $this->postal_code = $postal_code; + $DB->prepare("UPDATE `users` SET `postal_code` = ? WHERE `id` = ?;")->execute([$postal_code, $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 getPhoneNumber() + { + return $this->phone_number; + } + + public function setPhoneNumber($phone_number) + { + global $DB; + $this->phone_number = $phone_number; + $DB->prepare("UPDATE `users` SET `phone_number` = ? WHERE `id` = ?;")->execute([$phone_number, $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([SchoolClass::getName($school), $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 getResponsibleName() + { + return $this->responsible_name; + } + + public function setResponsibleName($responsible_name) + { + global $DB; + $this->responsible_name = $responsible_name; + $DB->prepare("UPDATE `users` SET `responsible_name` = ? WHERE `id` = ?;")->execute([$responsible_name, $this->getId()]); + } + + public function getResponsiblePhone() + { + return $this->responsible_phone; + } + + public function setResponsiblePhone($responsible_phone) + { + global $DB; + $this->responsible_phone = $responsible_phone; + $DB->prepare("UPDATE `users` SET `responsible_phone` = ? WHERE `id` = ?;")->execute([$responsible_phone, $this->getId()]); + } + + public function getResponsibleEmail() + { + return $this->responsible_email; + } + + public function setResponsibleEmail($responsible_email) + { + global $DB; + $this->responsible_email = $responsible_email; + $DB->prepare("UPDATE `users` SET `responsible_email` = ? WHERE `id` = ?;")->execute([$responsible_email, $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; + /** @noinspection PhpUndefinedMethodInspection */ + $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 getYear() + { + return $this->year; + } + + 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 getAllDocuments($tournament_id) + { + global $DB; + $req = $DB->query("SELECT * FROM `documents` AS `t1` " + . "INNER JOIN (SELECT `user`, `type`, `tournament`, MAX(`uploaded_at`) AS `last_upload`, COUNT(`team`) AS `version` FROM `documents` GROUP BY `tournament`, `type`, `user`) `t2` " + . "ON `t1`.`user` = `t2`.`user` AND `t1`.`type` = `t2`.`type` AND `t1`.`tournament` = `t2`.`tournament` " + . "WHERE `t1`.`uploaded_at` = `t2`.`last_upload` AND `t1`.`tournament` = $tournament_id AND `t1`.`user` = $this->id ORDER BY `t1`.`type`;"); + + $docs = []; + + while (($data = $req->fetch()) !== false) + $docs[] = Document::fromData($data); + + return $docs; + } + + public function getOrganizedTournaments() + { + global $DB; + $req = $DB->query("SELECT `tournament` FROM `organizers` JOIN `tournaments` ON `tournaments`.`id` = `tournament` WHERE `organizer` = $this->id ORDER BY `date_start`, `name`;"); + + $tournaments = []; + + while (($data = $req->fetch()) !== false) + $tournaments[] = Tournament::fromId($data["tournament"]); + + return $tournaments; + } +} \ No newline at end of file diff --git a/server_files/classes/ValidationStatus.php b/server_files/classes/ValidationStatus.php new file mode 100644 index 0000000..459d7ad --- /dev/null +++ b/server_files/classes/ValidationStatus.php @@ -0,0 +1,41 @@ + PDO::ERRMODE_EXCEPTION)); +} +catch (Exception $ex) { + die("Erreur lors de la connexion à la base de données : " . $ex->getMessage()); +} + +session_start(); +setlocale(LC_ALL, "fr_FR.utf8"); diff --git a/server_files/controllers/ajouter_equipe.php b/server_files/controllers/ajouter_equipe.php new file mode 100644 index 0000000..6043bcd --- /dev/null +++ b/server_files/controllers/ajouter_equipe.php @@ -0,0 +1,63 @@ +query("SELECT `id`, `name` FROM `tournaments` WHERE `date_inscription` > CURRENT_DATE AND `year` = '$YEAR';"); + +$has_error = false; +$error_message = null; + +if (isset($_POST["submitted"])) { + $new_team = new NewTeam($_POST); + try { + $new_team->makeVerifications(); + $new_team->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewTeam { + public $name; + public $trigram; + public $tournament_id; + public $tournament; + public $access_code; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() { + ensure($_SESSION["team"] == null, "Vous êtes déjà dans une équipe."); + ensure($this->name != null && $this->name != "", "Vous devez spécifier un nom d'équipe."); + 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."); + $this->tournament = Tournament::fromId($this->tournament_id); + ensure($this->tournament != null, "Le tournoi spécifié n'existe pas."); + } + + public function register() { + global $DB, $YEAR; + + $this->access_code = genRandomPhrase(6); + + $req = $DB->prepare("INSERT INTO `teams` (`name`, `trigram`, `tournament`, `encadrant_1`, `participant_1`, `validation_status`, `access_code`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->name, $this->trigram, $this->tournament_id, $_SESSION["role"] == Role::ENCADRANT ? $_SESSION["user_id"] : NULL, + $_SESSION["role"] == Role::PARTICIPANT ? $_SESSION["user_id"] : NULL, ValidationStatus::NOT_READY, $this->access_code, $YEAR]); + + $_SESSION["team"] = Team::fromTrigram($this->trigram); + $_SESSION["user"]->setTeamId($_SESSION["team"]->getId()); + + Mailer::sendAddTeamMail($_SESSION["user"], $_SESSION["team"], $this->tournament); + } +} + +require_once "server_files/views/ajouter_equipe.php"; diff --git a/server_files/controllers/ajouter_organisateur.php b/server_files/controllers/ajouter_organisateur.php new file mode 100644 index 0000000..dbb81b7 --- /dev/null +++ b/server_files/controllers/ajouter_organisateur.php @@ -0,0 +1,57 @@ +makeVerifications(); + $orga->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewOrganizer { + public $surname; + public $first_name; + public $email; + public $admin; + 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."); + $this->admin = $this->admin == "on" ? true : false; + } + + public function register() { + global $DB, $YEAR; + + $this->password = genRandomPhrase(16, true); + + $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `surname`, `first_name`, `role`, `year`) + VALUES (?, ?, ?, ?, ?, ?);"); + $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->surname, $this->first_name, $this->admin ? "ADMIN" : "ORGANIZER", $YEAR]); + + Mailer::sendAddOrganizerMail($this); + } +} + +require_once "server_files/views/ajouter_organisateur.php"; \ No newline at end of file diff --git a/server_files/controllers/ajouter_tournoi.php b/server_files/controllers/ajouter_tournoi.php new file mode 100644 index 0000000..b855ea2 --- /dev/null +++ b/server_files/controllers/ajouter_tournoi.php @@ -0,0 +1,104 @@ +query("SELECT `id`, `surname`, `first_name` FROM `users` WHERE (`role` = 'ORGANIZER' OR `role` = 'ADMIN') AND `year` = '$YEAR';"); + +$has_error = false; +$error_message = null; + +if (isset($_POST["submitted"])) { + $tournament = new NewTournament($_POST); + try { + $tournament->makeVerifications(); + $tournament->register(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewTournament { + public $name; + public $organizers; + public $size; + public $place; + public $price; + public $date_start; + public $date_end; + public $date_inscription; + public $time_inscription; + public $date_solutions; + public $time_solutions; + public $date_syntheses; + public $time_syntheses; + public $description; + public $final; + public $tournament; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = ($key == "organizers" ? $value : htmlspecialchars($value)); + } + + public function makeVerifications() + { + global $FINAL; + + ensure($this->name != null && $this->name != "", "Le nom est invalide."); + ensure(!tournamentExists($this->name), "Un tournoi existe déjà avec ce nom."); + ensure(sizeof($this->organizers) > 0, "Aucun organisateur n'a été choisi."); + + $orgas = []; + foreach ($this->organizers as $orga_id) { + $orga = User::fromId($orga_id); + ensure($orga != null, "Un organisateur spécifié n'existe pas."); + ensure($orga->getRole() == Role::ORGANIZER || $orga->getRole() == Role::ADMIN, "Une personne indiquée ne peut pas organiser de tournoi."); + $orgas[] = $orga; + } + $this->organizers = $orgas; + + ensure(preg_match("#[0-9]*#", $this->size), "Le nombre d'équipes indiqué n'est pas un nombre valide."); + $this->size = intval($this->size); + ensure($this->size >= 3 && $this->size <= 15, "Un tournoi doit avoir au moins 3 et au plus 15 équipes."); + + ensure(preg_match("#[0-9]*#", $this->price), "Le tarif pour les participants n'est pas un entier valide."); + $this->price = intval($this->price); + ensure($this->price >= 0, "Le TFJM² ne va pas payer les élèves pour venir."); + ensure($this->price <= 50, "Soyons raisonnable sur le prix."); + + ensure(dateWellFormed($this->date_start), "La date de début n'est pas valide."); + ensure(dateWellFormed($this->date_end), "La date de fin n'est pas valide."); + ensure(dateWellFormed($this->date_inscription . " " . $this->time_inscription), "La date de clôture des inscriptions n'est pas valide."); + ensure(dateWellFormed($this->date_solutions . " " . $this->time_solutions), "La date limite de remise des solutions n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses . " " . $this->time_syntheses), "La date limite de remise des notes de synthèse n'est pas valide."); + + $this->final = $this->final ? 1 : 0; + + ensure(!$this->final || $FINAL == NULL, "Une finale nationale est déjà enregistrée."); + } + + public function register() + { + global $DB, $YEAR; + + $req = $DB->prepare("INSERT INTO `tournaments` (`name`, `size`, `place`, `price`, `description`, + `date_start`, `date_end`, `date_inscription`, `date_solutions`, `date_syntheses`, `final`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->name, $this->size, $this->place, $this->price, $this->description, $this->date_start, $this->date_end, + "$this->date_inscription $this->time_inscription", "$this->date_solutions $this->time_solutions", "$this->date_syntheses $this->time_syntheses", $this->final ? 1 : 0, $YEAR]); + + $this->tournament = Tournament::fromName($this->name); + + /** @var User $organizer */ + foreach ($this->organizers as $organizer) { + $this->tournament->addOrganizer($organizer); + Mailer::sendAddOrganizerForTournamentMail($organizer, $this->tournament); + } + } +} + +require_once "server_files/views/ajouter_tournoi.php"; diff --git a/server_files/controllers/confirmer_mail.php b/server_files/controllers/confirmer_mail.php new file mode 100644 index 0000000..abe2e58 --- /dev/null +++ b/server_files/controllers/confirmer_mail.php @@ -0,0 +1,19 @@ +query("SELECT `email` FROM `users` WHERE `confirm_email` = '$token' AND `year` = '$YEAR';"); + if (($data = $result->fetch()) === FALSE) + $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 { + $error_message = "Il n'y a pas de compte à valider !"; +} +require_once "server_files/views/header.php"; +echo "

$error_message

"; +require_once "server_files/views/footer.php"; diff --git a/server_files/controllers/connexion.php b/server_files/controllers/connexion.php new file mode 100644 index 0000000..2fe94b2 --- /dev/null +++ b/server_files/controllers/connexion.php @@ -0,0 +1,170 @@ +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() + { + global $URL_BASE; + + 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; + 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(); + 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 ($this->password == null) + 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 new file mode 100644 index 0000000..141953d --- /dev/null +++ b/server_files/controllers/deconnexion.php @@ -0,0 +1,8 @@ +Déconnexion réussie !"; +require_once "server_files/views/footer.php"; diff --git a/server_files/controllers/equipe.php b/server_files/controllers/equipe.php new file mode 100644 index 0000000..14d1b13 --- /dev/null +++ b/server_files/controllers/equipe.php @@ -0,0 +1,57 @@ +getTournamentId()); + +if ($team === null) + require_once "server_files/404.php"; + +if (isset($_POST["validate"])) { + $team->setValidationStatus(ValidationStatus::VALIDATED); +} + +if (isset($_POST["select"])) { + $team->selectForFinal(true); + $team->setValidationStatus(ValidationStatus::NOT_READY); + $sols = $tournament->getAllSolutions($team->getId()); + /** @var Solution $sol */ + foreach ($sols as $sol) { + $old_id = $sol->getFileId(); + do + $id = genRandomPhrase(64); + while (file_exists("$LOCAL_PATH/files/$id")); + + copy("$LOCAL_PATH/files/$old_id", "$LOCAL_PATH/files/$id"); + + $req = $DB->prepare("INSERT INTO `solutions`(`file_id`, `team`, `tournament`, `problem`) VALUES (?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $FINAL->getId(), $sol->getFileId()]); + } +} + +if (isset($_POST["download_zip"])) { + $final = isset($_POST["final"]); + $tournament_dest = $final ? $FINAL : $tournament; + + $file_name = getZipFile(DocumentType::PARENTAL_CONSENT, $tournament_dest->getId(), $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(); +} + +$documents = $tournament->getAllDocuments($team->getId()); +$documents_final = null; + +if ($team->isSelectedForFinal()) + $documents_final = $FINAL->getAllDocuments($team->getId()); + +require_once "server_files/views/equipe.php"; diff --git a/server_files/controllers/index.php b/server_files/controllers/index.php new file mode 100644 index 0000000..a884dca --- /dev/null +++ b/server_files/controllers/index.php @@ -0,0 +1,3 @@ +getId() != $_SESSION["user_id"] && ($user->getTeamId() == null || $user->getTeamId() != $_SESSION["user"]->getTeamId())) + require_once "server_files/403.php"; +} + +if ($user === null) + require_once "server_files/404.php"; + +$team = Team::fromId($user->getTeamId()); +$tournaments = $user->getOrganizedTournaments(); + +if ($team != null) { + $documents = $user->getAllDocuments($team->getTournamentId()); + if ($team->isSelectedForFinal()) + $documents_final = $user->getAllDocuments($FINAL->getId()); +} + +require_once "server_files/views/informations.php"; diff --git a/server_files/controllers/inscription.php b/server_files/controllers/inscription.php new file mode 100644 index 0000000..3f1462a --- /dev/null +++ b/server_files/controllers/inscription.php @@ -0,0 +1,93 @@ +makeVerifications(); + $user->register(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class NewUser +{ + public $email; + public $first_name; + public $surname; + public $birth_date; + public $gender; + public $address = ""; + public $postal_code; + public $city = ""; + public $country; + public $phone_number; + public $role; + public $school; + public $class; + public $responsible_name; + public $responsible_phone; + public $responsible_email; + public $description; + public $confirm_email_token; + private $password; + private $confirm_password; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + } + + public function makeVerifications() + { + global $YEAR; + + 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."); + ensure(dateWellFormed($this->birth_date), "La date de naissance est invalide."); + ensure($this->birth_date < $YEAR . "-01-01", "Vous devez être né."); + ensure($this->gender == "M" || $this->gender == "F", "Le sexe indiqué est invalide."); + ensure(preg_match("#^[0-9]{4}[0-9]?$#", $this->postal_code) && intval($this->postal_code) >= 01000 && intval($this->postal_code) <= 95999, "Le code postal est invalide."); + if ($this->country == "") + $this->country = "France"; + ensure(strlen($this->phone_number) >= 10, "Le numéro de téléphone est invalide."); + $this->role = Role::fromName(strtoupper($this->role)); + + if ($this->role == Role::PARTICIPANT) { + $this->class = SchoolClass::fromName(strtoupper($this->class)); + if ($this->birth_date > strval($YEAR - 18) . "04-01") { + ensure($this->responsible_name != "", "Veuillez spécifier un responsable légal."); + ensure(strlen($this->responsible_phone) >= 10, "Veuillez rentrer le numéro de téléphone de votre responsable légal."); + ensure(filter_var($this->responsible_email, FILTER_VALIDATE_EMAIL), "Veuillez spécifier un responsable légal."); + } + } + + $this->confirm_email_token = genRandomPhrase(64); + } + + public function register() + { + global $DB, $YEAR; + + $req = $DB->prepare("INSERT INTO `users`(`email`, `pwd_hash`, `confirm_email`, `surname`, `first_name`, `birth_date`, `gender`, + `address`, `postal_code`, `city`, `country`, `phone_number`, `school`, `class`, `role`, `description`, `year`) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);"); + $req->execute([$this->email, password_hash($this->password, PASSWORD_BCRYPT), $this->confirm_email_token, $this->surname, $this->first_name, $this->birth_date, $this->gender, $this->address, + $this->postal_code, $this->city, $this->country, $this->phone_number, $this->school, SchoolClass::getName($this->class), Role::getName($this->role), $this->description, $YEAR]); + + Mailer::sendRegisterMail($this); + } +} + +require_once "server_files/views/inscription.php"; diff --git a/server_files/controllers/mon_compte.php b/server_files/controllers/mon_compte.php new file mode 100644 index 0000000..b4f799b --- /dev/null +++ b/server_files/controllers/mon_compte.php @@ -0,0 +1,152 @@ +makeVerifications(); + $my_account->updateAccount(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["submitted_password"])) { + $new_password = new NewPassword($_POST); + try { + $new_password->makeVerifications(); + $new_password->updatePassword(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +class MyAccount +{ + public $email; + public $surname; + public $first_name; + public $birth_date; + public $gender; + public $address; + public $postal_code; + public $city; + public $country; + public $phone_number; + public $school; + public $class; + public $responsible_name; + public $responsible_phone; + public $responsible_email; + public $description; + private $user; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->user = $_SESSION["user"]; + + $keys = ["email", "surname", "first_name", "birth_date", "gender", "address", "postal_code", "city", "country", "phone_number", + "school", "class", "responsible_name", "responsible_phone", "responsible_email", "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; + } + + public function makeVerifications() + { + global $YEAR; + + 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."); + ensure(dateWellFormed($this->birth_date), "La date de naissance est invalide."); + ensure($this->birth_date < $YEAR . "-01-01", "Vous devez être né."); + ensure($this->gender == "M" || $this->gender == "F", "Le sexe indiqué est invalide."); + ensure(preg_match("#^[0-9]{4}[0-9]?$#", $this->postal_code) && intval($this->postal_code) >= 01000 && intval($this->postal_code) <= 95999, "Le code postal est invalide."); + ensure(strlen($this->phone_number) >= 10, "Le numéro de téléphone est invalide."); + + if ($this->user->getRole() == Role::PARTICIPANT) { + if ($this->birth_date > strval($YEAR - 18) . "04-01") { + ensure($this->responsible_name != "", "Veuillez spécifier un responsable légal."); + ensure(strlen($this->responsible_phone) >= 10, "Veuillez rentrer le numéro de téléphone de votre responsable légal."); + ensure(filter_var($this->responsible_email, FILTER_VALIDATE_EMAIL), "Veuillez spécifier un responsable légal."); + } + } + } + + public function updateAccount() + { + $this->user->setSurname($this->surname); + $this->user->setFirstName($this->first_name); + $this->user->setBirthDate($this->birth_date); + $this->user->setGender($this->gender); + $this->user->setAddress($this->address); + $this->user->setPostalCode($this->postal_code); + $this->user->setCity($this->city); + $this->user->setCountry($this->country); + $this->user->setPhoneNumber($this->phone_number); + $this->user->setSchool($this->school); + $this->user->setClass($this->class); + $this->user->setResponsibleName($this->responsible_name); + $this->user->setResponsiblePhone($this->responsible_phone); + $this->user->setResponsibleEmail($this->responsible_email); + $this->user->setDescription($this->description); + + 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); + } +} + +require_once "server_files/views/mon_compte.php"; diff --git a/server_files/controllers/mon_equipe.php b/server_files/controllers/mon_equipe.php new file mode 100644 index 0000000..bb14051 --- /dev/null +++ b/server_files/controllers/mon_equipe.php @@ -0,0 +1,141 @@ +makeVerifications(); + $send_document->sendDocument(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["team_edit"])) { + $my_team = new MyTeam($_POST); + try { + $my_team->makeVerifications(); + $my_team->updateTeam(); + } + catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +if (isset($_POST["request_validation"])) { + if (!canValidate($team, $tournament)) + $error_message = "Votre équipe ne peut pas demander la validation : il manque soit des participants, soit des documents."; + else + $_SESSION["team"]->setValidationStatus(ValidationStatus::WAITING); +} + +if (isset($_SESSION["user_id"]) && isset($_SESSION["team"]) && $_SESSION["team"] !== null) { + /** + * @var User $user + * @var Team $team + */ + $user = $_SESSION["user"]; + $team = $_SESSION["team"]; + + $tournament = Tournament::fromId($team->getTournamentId()); + $documents = $user->getAllDocuments($team->getTournamentId()); + if ($team->isSelectedForFinal()) + $documents_final = $user->getAllDocuments($FINAL->getId()); +} +else + require_once "server_files/403.php"; + +class SendDocument +{ + private $file; + private $type; + + public function __construct() + { + $this->file = $_FILES["document"]; + $this->type = strtoupper(htmlspecialchars($_POST["type"])); + } + + 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."); + ensure(finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]) == "application/pdf", "Le fichier doit être au format PDF."); + 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 sendDocument() + { + global $LOCAL_PATH, $DB, $FINAL; + + 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`, `tournament`, `type`) + VALUES (?, ?, ?, ?, ?);"); + $req->execute([$id, $_SESSION["user_id"], $_SESSION["team"]->getId(), $_SESSION["team"]->isSelectedForFinal() ? $FINAL->getId() : $_SESSION["team"]->getTournamentId(), $this->type]); + } +} + +class MyTeam +{ + public $name; + public $trigram; + public $tournament_id; + private $team; + private $tournament; + + public function __construct($data) + { + foreach ($data as $key => $value) + $this->$key = htmlspecialchars($value); + + $this->trigram = strtoupper($this->trigram); + $this->team = $_SESSION["team"]; + $this->tournament = Tournament::fromId($this->tournament_id); + } + + public function makeVerifications() + { + 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("#^[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($this->tournament != null, "Le tournoi indiqué n'existe pas."); + ensure(date("y-m-d H:i:s") <= $this->tournament->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 $URL_BASE; + + $this->team->setName($this->name); + $this->team->setTrigram($this->trigram); + $this->team->setTournamentId($this->tournament_id); + + $_SESSION["tournament"] = $this->tournament; + + header("Location: $URL_BASE/mon_equipe"); + } +} + +require_once "server_files/views/mon_equipe.php"; diff --git a/server_files/controllers/rejoindre_equipe.php b/server_files/controllers/rejoindre_equipe.php new file mode 100644 index 0000000..dadcf35 --- /dev/null +++ b/server_files/controllers/rejoindre_equipe.php @@ -0,0 +1,66 @@ +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() + { + 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 ? 6 : 2; ++$i) { + if (($_SESSION["role"] == Role::PARTICIPANT ? $this->team->getParticipants()[$i - 1] : $this->team->getEncadrants()[$i - 1]) == NULL) + break; + } + + $this->min_null_index = $i; + + ensure($_SESSION["role"] == Role::PARTICIPANT && $this->min_null_index <= 6 || $_SESSION["role"] == Role::ENCADRANT && $this->min_null_index <= 2, "Il n'y a plus de place pour vous dans l'équipe."); + } + + public function joinTeam() + { + $user = $_SESSION["user"]; + + $user->setTeamId($this->team->getId()); + + if ($_SESSION["role"] == Role::ENCADRANT) + $this->team->setEncadrant($this->min_null_index, $user->getId()); + else + $this->team->setParticipant($this->min_null_index, $user->getId()); + + $_SESSION["team"] = $this->team; + $tournament = $_SESSION["tournament"] = Tournament::fromId($this->team->getTournamentId()); + + Mailer::sendJoinTeamMail($user, $this->team, $tournament); + } +} + +require_once "server_files/views/rejoindre_equipe.php"; diff --git a/server_files/controllers/solutions.php b/server_files/controllers/solutions.php new file mode 100644 index 0000000..cab37a5 --- /dev/null +++ b/server_files/controllers/solutions.php @@ -0,0 +1,72 @@ +getTournamentId()); + +$has_error = false; +$error_message = null; + +if (isset($_POST["send_solution"])) { + $save_solution = new SaveSolution(); + try { + $save_solution->makeVerifications(); + $save_solution->saveSolution(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$solutions = $tournament->getAllSolutions($team->getId()); +$solutions_final = null; +if ($team->isSelectedForFinal()) + $solutions_final = $FINAL->getAllSolutions($team->getId()); + +class SaveSolution +{ + private $problem; + private $file; + + public function __construct() + { + $this->file = $_FILES["document"]; + $this->problem = htmlspecialchars($_POST["problem"]); + } + + public function makeVerifications() + { + global $LOCAL_PATH; + + ensure(preg_match("#[1-9]#", $this->problem), "Le numéro du problème est invalide."); + ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); + ensure(!$this->file["error"], "Une erreur est survenue."); + ensure(finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]) == "application/pdf", "Le fichier doit être au format PDF."); + 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 saveSolution() + { + global $LOCAL_PATH, $DB, $team, $tournament, $FINAL; + + 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 `solutions`(`file_id`, `team`, `tournament`, `problem`) VALUES (?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $team->isSelectedForFinal() ? $FINAL->getId() : $tournament->getId(), $this->problem]); + + return false; + } +} + +require_once "server_files/views/solutions.php"; diff --git a/server_files/controllers/solutions_orga.php b/server_files/controllers/solutions_orga.php new file mode 100644 index 0000000..945c9f8 --- /dev/null +++ b/server_files/controllers/solutions_orga.php @@ -0,0 +1,24 @@ +getName() . ".zip\""); + header("Content-Length: " . strval(filesize($file_name))); + + readfile($file_name); + + exit(); +} + +$user = $_SESSION["user"]; +$tournaments = $_SESSION["role"] == Role::ADMIN ? Tournament::getAllTournaments() : $user->getOrganizedTournaments(); + +require_once "server_files/views/solutions_orga.php"; diff --git a/server_files/controllers/syntheses.php b/server_files/controllers/syntheses.php new file mode 100644 index 0000000..e2e2ec7 --- /dev/null +++ b/server_files/controllers/syntheses.php @@ -0,0 +1,68 @@ +getTournamentId()); + +if (isset($_POST["send_synthesis"])) { + $save_synthesis = new SaveSynthesis(); + try { + $save_synthesis->makeVerifications(); + $save_synthesis->saveSynthesis(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$syntheses = $tournament->getAllSyntheses($team->getId()); +$syntheses_final = null; +if ($team->isSelectedForFinal()) + $syntheses_final = $FINAL->getAllSyntheses($team->getId()); + +class SaveSynthesis +{ + private $dest; + private $file; + + public function __construct() + { + $this->file = $_FILES["document"]; + $this->dest = DestType::fromName(strtoupper(htmlspecialchars($_POST["problem"]))); + } + + public function makeVerifications() + { + global $LOCAL_PATH; + + ensure($this->dest != DestType::DEFENSEUR, "Le destinataire est invalide."); + ensure($this->file["size"] <= 2e6, "Le fichier doit peser moins que 2 Mo."); + ensure(!$this->file["error"], "Une erreur est survenue."); + ensure(finfo_file(finfo_open(FILEINFO_MIME_TYPE), $this->file["tmp_name"]) == "application/pdf", "Le fichier doit être au format PDF."); + 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 saveSynthesis() + { + global $LOCAL_PATH, $DB, $team, $tournament, $FINAL; + 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 `syntheses`(`file_id`, `team`, `tournament`, `dest`) VALUES (?, ?, ?, ?);"); + $req->execute([$id, $team->getId(), $team->isSelectedForFinal() ? $FINAL->getId() : $tournament->getId(), $this->dest]); + + return false; + } +} + +require_once "server_files/views/syntheses.php"; diff --git a/server_files/controllers/syntheses_orga.php b/server_files/controllers/syntheses_orga.php new file mode 100644 index 0000000..c4415e2 --- /dev/null +++ b/server_files/controllers/syntheses_orga.php @@ -0,0 +1,22 @@ +getName() . ".zip\""); + header("Content-Length: " . filesize($file_name)); + + readfile($file_name); + + exit(); +} + +$user = $_SESSION["user"]; +$tournaments = $_SESSION["role"] == Role::ADMIN ? Tournament::getAllTournaments() : $user->getOrganizedTournaments(); + +require_once "server_files/views/syntheses_orga.php"; \ No newline at end of file diff --git a/server_files/controllers/tournoi.php b/server_files/controllers/tournoi.php new file mode 100644 index 0000000..ce716cc --- /dev/null +++ b/server_files/controllers/tournoi.php @@ -0,0 +1,125 @@ +organize($_SESSION["user_id"])) + require_once "server_files/403.php"; + +$has_error = false; +$error_message = null; + +if (isset($_POST["edit_tournament"])) { + $update_tournament = new UpdateTournament($_POST); + try { + $update_tournament->makeVerifications(); + $update_tournament->updateTournament(); + } catch (AssertionError $e) { + $has_error = true; + $error_message = $e->getMessage(); + } +} + +$orgas = $tournament->getOrganizers(); +$teams = $tournament->getAllTeams(); +$orgas_response = $DB->query("SELECT `id`, `surname`, `first_name` FROM `users` WHERE (`role` = 'ORGANIZER' OR `role` = 'ADMIN') AND `year` = '$YEAR';"); + +class UpdateTournament +{ + public $name; + public $organizers; + public $size; + public $place; + public $price; + public $date_start; + public $date_end; + public $date_inscription; + public $time_inscription; + public $date_solutions; + public $time_solutions; + public $date_syntheses; + public $time_syntheses; + public $description; + public $final; + + public function __construct($data) + { + global $tournament; + + foreach ($data as $key => $value) + $this->$key = ($key == "organizers" ? $value : htmlspecialchars($value)); + + if ($_SESSION["role"] != Role::ADMIN) { + $this->organizers = []; + /** @var User $organizer */ + foreach ($tournament->getOrganizers() as $organizer) + $this->organizers[] = $organizer->getId(); + } + } + + public function makeVerifications() + { + global $tournament; + + ensure($this->name != null && $this->name != "", "Le nom est invalide."); + ensure($this->name == $tournament->getName() || !tournamentExists($this->name), "Un tournoi existe déjà avec ce nom."); + ensure(sizeof($this->organizers) > 0, "Aucun organisateur n'a été choisi."); + + $orgas = []; + foreach ($this->organizers as $orga_id) { + $orga = User::fromId($orga_id); + ensure($orga != null, "Un organisateur spécifié n'existe pas."); + ensure($orga->getRole() == Role::ORGANIZER || $orga->getRole() == Role::ADMIN, "Une personne indiquée ne peut pas organiser de tournoi."); + $orgas[] = $orga; + } + $this->organizers = $orgas; + + ensure(preg_match("#[0-9]*#", $this->size), "Le nombre d'équipes indiqué n'est pas un nombre valide."); + $this->size = intval($this->size); + ensure($this->size >= 3 && $this->size <= 15, "Un tournoi doit avoir au moins 3 et au plus 15 équipes."); + + ensure(preg_match("#[0-9]*#", $this->price), "Le tarif pour les participants n'est pas un entier valide."); + $this->price = intval($this->price); + ensure($this->price >= 0, "Le TFJM² ne va pas payer les élèves pour venir."); + ensure($this->price <= 50, "Soyons raisonnable sur le prix."); + + ensure(dateWellFormed($this->date_start), "La date de début n'est pas valide."); + ensure(dateWellFormed($this->date_end), "La date de fin n'est pas valide."); + ensure(dateWellFormed($this->date_inscription . " " . $this->time_inscription), "La date de clôture des inscriptions n'est pas valide."); + ensure(dateWellFormed($this->date_solutions . " " . $this->time_solutions), "La date limite de remise des solutions n'est pas valide."); + ensure(dateWellFormed($this->date_syntheses . " " . $this->time_syntheses), "La date limite de remise des notes de synthèse n'est pas valide."); + } + + public function updateTournament() + { + global $URL_BASE, $tournament; + + $tournament->setName($this->name); + $tournament->setSize($this->size); + $tournament->setPlace($this->place); + $tournament->setPrice($this->price); + $tournament->setStartDate($this->date_start); + $tournament->setEndDate($this->date_end); + $tournament->setInscriptionDate("$this->date_inscription $this->time_inscription"); + $tournament->setSolutionsDate("$this->date_solutions $this->time_solutions"); + $tournament->setSynthesesDate("$this->date_syntheses $this->time_syntheses"); + + foreach ($this->organizers as $organizer) { + if (!$tournament->organize($organizer->getId())) + Mailer::sendAddOrganizerForTournamentMail($organizer, $tournament); + } + + $tournament->clearOrganizers(); + /** @var User $organizer */ + foreach ($this->organizers as $organizer) + $tournament->addOrganizer($organizer); + + header("Location: $URL_BASE/tournoi/" . $this->name); + exit(); + } +} + +require_once "server_files/views/tournoi.php"; diff --git a/server_files/controllers/tournois.php b/server_files/controllers/tournois.php new file mode 100644 index 0000000..db4c402 --- /dev/null +++ b/server_files/controllers/tournois.php @@ -0,0 +1,5 @@ +getTeamId()); + $tournament = Tournament::fromId($file->getTournamentId()); + $trigram = $team->getTrigram(); + + if ($_SESSION["role"] == Role::ORGANIZER && !$tournament->organize($_SESSION["user_id"])) + require_once "server_files/403.php"; + + if ($type == DocumentType::SOLUTION) { + $problem = $file->getProblem(); + $name = "Problème $problem $trigram.pdf"; + + if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT) && (!isset($_SESSION["team"]) || $_SESSION["team"]->getId() != $team->getId())) + require_once "server_files/403.php"; + } + else if ($type == DocumentType::SYNTHESIS) { + $dest = $file->getDest(); + $name = "Note de synthèse $trigram pour " . ($dest == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") . ".pdf"; + + if (($_SESSION["role"] == Role::PARTICIPANT || $_SESSION["role"] == Role::ENCADRANT) && (!isset($_SESSION["team"]) || $_SESSION["team"]->getId() != $team->getId())) + require_once "server_files/403.php"; + } + else { + $user = User::fromId($file->getUserId()); + $type = $file->getType(); + + 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(); + switch ($type) { + case DocumentType::PARENTAL_CONSENT: + $name = "Autorisation parentale"; + break; + case DocumentType::PHOTO_CONSENT: + $name = "Autorisation de droit à l'image"; + break; + case DocumentType::SANITARY_PLUG: + $name = "Fiche sanitaire"; + break; + } + $name .= " de $first_name $surname.pdf"; + } +} +else + require_once "server_files/404.php"; + +header("Content-Type: application/pdf"); +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 new file mode 100644 index 0000000..0587714 --- /dev/null +++ b/server_files/model.php @@ -0,0 +1,251 @@ +getRole(); + + if ($user->getTeamId() !== null) { + $team = $_SESSION["team"] = Team::fromId($user->getTeamId()); + $_SESSION["tournament"] = Tournament::fromId($team->getTournamentId()); + } + + if (isset($_GET["be-admin"])) { + quitTeam(); + $user->setRole(Role::ADMIN); + exit(); + } + + if (isset($_GET["be-organizer"])) { + quitTeam(); + $user->setRole(Role::ORGANIZER); + exit(); + } + + if (isset($_GET["be-participant"])) { + quitTeam(); + $user->setRole(Role::PARTICIPANT); + exit(); + } + + if (isset($_GET["be-encadrant"])) { + quitTeam(); + $user->setRole(Role::ENCADRANT); + exit(); + } + } +} + +function quitTeam() +{ + global $DB, $URL_BASE; + + header("Location: $URL_BASE"); + + /** @var User $user */ + $user = $_SESSION["user"]; + $user_id = $user->getId(); + $role = $user->getRole(); + + if ($role == Role::ADMIN || $role == Role::ORGANIZER) + return; + + for ($i = 1; $i <= ($role == Role::ENCADRANT ? 2 : 6); ++$i) + /** @noinspection SqlResolve */ + $DB->exec("UPDATE `teams` SET `" . strtolower(Role::getName($role)) . "_$i` = NULL WHERE `" . strtolower(Role::getName($role)) . "_$i` = $user_id;"); + $user->setTeamId(null); + $DB->exec("UPDATE `teams` SET `encadrant_1` = `encadrant_2`, `encadrant_2` = NULL WHERE `encadrant_1` IS NULL;"); + for ($i = 1; $i <= 5; ++$i) { + /** @noinspection SqlResolve */ + $DB->exec("UPDATE `teams` SET `participant_$i` = `participant_" . strval($i + 1) . "`, `participant_" . strval($i + 1) . "` = NULL WHERE `participant_$i` 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;"); + + if ($DB->exec("DELETE FROM `teams` WHERE `encadrant_1` IS NULL AND `participant_1` IS NULL;") > 0) { + $team_id = $user->getTeamId(); + $req = $DB->query("SELECT `file_id` FROM `solutions` WHERE `team` = $team_id;"); + while (($data = $req->fetch()) !== false) + unlink("$URL_BASE/files/" . $data["file_id"]); + $DB->exec("DELETE FROM `solutions` WHERE `team` = $team_id;"); + + $req = $DB->query("SELECT `file_id` FROM `syntheses` WHERE `team` = $team_id;"); + while (($data = $req->fetch()) !== false) + unlink("$URL_BASE/files/" . $data["file_id"]); + $DB->exec("DELETE FROM `syntheses` WHERE `team` = $team_id;"); + } + + $_SESSION["team"] = null; + unset($_SESSION["team"]); +} + +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 tournamentExists($name) +{ + global $DB, $YEAR; + + $req = $DB->prepare("SELECT `id` FROM `tournaments` WHERE `name` = ? AND `year` = '$YEAR';"); + $req->execute([$name]); + return $req->fetch(); +} + +function canValidate(Team $team, Tournament $tournament) +{ + global $DB, $YEAR; + + $can_validate = $team->getValidationStatus() == ValidationStatus::NOT_READY; + $can_validate &= $team->getEncadrants()[0] != NULL; + $can_validate &= $team->getParticipants()[3] != NULL; + for ($i = 1; $i <= 2; ++$i) { + if ($team->getEncadrants()[$i - 1] === NULL) + continue; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getEncadrants()[$i - 1], $tournament->getId(), "PHOTO_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getEncadrants()[$i - 1], $tournament->getId(), "SANITARY_PLUG"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + } + for ($i = 1; $i <= 6; ++$i) { + if ($team->getParticipants()[$i] === NULL) + continue; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "PHOTO_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "SANITARY_PLUG"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + + $birth_date = $DB->query("SELECT `birth_date` FROM `users` WHERE `id` = " . $team->getParticipants()[$i] . ";")->fetch()["birth_date"]; + if ($birth_date > strval($YEAR - 18) . substr($tournament->getStartDate(), 4)) { + $req = $DB->prepare("SELECT COUNT(*) AS `version` FROM `documents` WHERE `user` = ? AND `tournament` = ? AND `type` = ?;"); + $req->execute([$team->getParticipants()[$i], $tournament->getId(), "PARENTAL_CONSENT"]); + $d = $req->fetch(); + $can_validate &= $d["version"] > 0; + } + } + + return $can_validate; +} + +function printDocuments($documents) +{ + global $URL_BASE; + + foreach ($documents as $document) { + $file_id = $document->getFileId(); + $user = User::fromId($document->getUserId()); + $surname = $user->getSurname(); + $first_name = $user->getFirstName(); + $name = DocumentType::getTranslatedName($document->getType()); + $version = $document->getVersion(); + echo "$name de $first_name $surname (version $version) : Télécharger
"; + } +} + +function getZipFile($document_type, $tournament_id, $team_id = -1) +{ + global $LOCAL_PATH; + + $tournament = Tournament::fromId($tournament_id); + + $zip = new ZipArchive(); + + $file_name = tempnam("tmp", "tfjm-"); + + if ($zip->open($file_name, ZipArchive::CREATE) !== true) { + die("Impossible de créer le fichier zip."); + } + + switch ($document_type) { + case DocumentType::SOLUTION: + $data = $tournament->getAllSolutions($team_id); + break; + case DocumentType::SYNTHESIS: + $data = $tournament->getAllSyntheses($team_id); + break; + default: + $data = $tournament->getAllDocuments($team_id); + break; + } + + /** @var Document | Solution | Synthesis $file */ + foreach ($data as $file) { + $file_id = $file->getFileId(); + $team = Team::fromId($file->getTeamId()); + switch ($document_type) { + case DocumentType::SOLUTION: + $name = "Problème " . $file->getProblem() . " " . $team->getTrigram() . ".pdf"; + break; + case DocumentType::SYNTHESIS: + $name = "Note de synthèse " . $team->getTrigram() . " pour " . ($file->getDest() == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") . ".pdf"; + break; + default: + $user = User::fromId($file->getUserId()); + switch ($file->getType()) { + case DocumentType::PARENTAL_CONSENT: + $name = "Autorisation parentale de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + case DocumentType::PHOTO_CONSENT: + $name = "Autorisation de droit à l'image de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + default: + $name = "Fiche sanitaire de " . $user->getFirstName() . " " . $user->getSurname() . ".pdf"; + break; + } + break; + } + + $zip->addFile("$LOCAL_PATH/files/$file_id", $name); + } + + $zip->close(); + + return $file_name; +} \ No newline at end of file diff --git a/server_files/services/mail.php b/server_files/services/mail.php new file mode 100644 index 0000000..18be95b --- /dev/null +++ b/server_files/services/mail.php @@ -0,0 +1,130 @@ +\r\n"; + $headers .= "Reply-To: \"Contact TFJM²\" \r\n"; + $headers .= "Content-Type: text/html; charset=UTF-8\r\n"; + + mail($email, $subject, $content, $headers); + } + + 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 au TFJM² $YEAR", $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 – TFJM² $YEAR", $content); + } + + public static function sendChangeEmailAddressMail(User $user) + { + $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 – TFJM²", $content); + } + + public static function sendForgottenPasswordProcedureMail(User $user) + { + $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é – TFJM²", $content); + } + + public static function sendChangePasswordMail(User $user) + { + $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é – TFJM²", $content); + } + + public static function sendAddTeamMail(User $user, Team $team, Tournament $tournament) + { + 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("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + $content = preg_replace("#{ACCESS_CODE}#", $team->getAccessCode(), $content); + + self::sendMail($user->getEmail(), "Ajout d'une équipe TFJM² $YEAR", $content); + } + + public static function sendJoinTeamMail(User $user, Team $team, Tournament $tournament) + { + 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); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + + self::sendMail($user->getEmail(), "Équipe rejointe TFJM² $YEAR", $content); + } + + public static function sendAddOrganizerMail(NewOrganizer $new_orga) + { + global $YEAR; + + $content = self::getTemplate("add_organizer"); + $content = preg_replace("#{FIRST_NAME}#", $new_orga->first_name, $content); + $content = preg_replace("#{SURNAME}#", $new_orga->surname, $content); + $content = preg_replace("#{PASSWORD}#", $new_orga->password, $content); + + self::sendMail($new_orga->email, "Ajout d'un organisateur – TFJM² $YEAR", $content); + } + + public static function sendAddOrganizerForTournamentMail(User $organizer, Tournament $tournament) + { + global $YEAR; + + $content = self::getTemplate("add_organizer_for_tournament"); + $content = preg_replace("#{FIRST_NAME}#", $organizer->getFirstName(), $content); + $content = preg_replace("#{SURNAME}#", $organizer->getSurname(), $content); + $content = preg_replace("#{TOURNAMENT_NAME}#", $tournament->getName(), $content); + + self::sendMail($organizer->getEmail(), "Ajout d'un organisateur pour le tournoi " . $tournament->getName() . " – TFJM² $YEAR", $content); + } +} diff --git a/server_files/services/mail_templates/add_organizer.html b/server_files/services/mail_templates/add_organizer.html new file mode 100644 index 0000000..d0331e1 --- /dev/null +++ b/server_files/services/mail_templates/add_organizer.html @@ -0,0 +1,21 @@ + + + + + Organisateur du TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous recevez ce message (envoyé automatiquement) car vous êtes organisateur d'un des tournois du TFJM2. +Veuillez trouver ci-dessous vos informations d'utilisateur pour le site officiel des inscriptions. Elles vous permettront de gérer les inscriptions des équipes de votre tournoi.
+
+Votre mot de passe est : {PASSWORD}
+
+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 !
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/add_organizer_for_tournament.html b/server_files/services/mail_templates/add_organizer_for_tournament.html new file mode 100644 index 0000000..a61ace2 --- /dev/null +++ b/server_files/services/mail_templates/add_organizer_for_tournament.html @@ -0,0 +1,17 @@ + + + + + + Organisateur du tournoi de {TOURNAMENT_NAME} – TFJM² + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez d'être promu organisateur du tournoi {TOURNAMENT_NAME} du TFJM2 {YEAR}.
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..ffd2b50 --- /dev/null +++ b/server_files/services/mail_templates/add_team.html @@ -0,0 +1,16 @@ + + + + + Nouvelle équipe TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de créer l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour le TFJM2 de {TOURNAMENT_NAME} 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é national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..0adf015 --- /dev/null +++ b/server_files/services/mail_templates/change_email_address.html @@ -0,0 +1,16 @@ + + + + + + Changement d'adresse e-mail – TFJM² + + +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é national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..91d2cf1 --- /dev/null +++ b/server_files/services/mail_templates/change_password.html @@ -0,0 +1,18 @@ + + + + + Mot de passe changé – TFJM² + + +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é national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..ba75174 --- /dev/null +++ b/server_files/services/mail_templates/confirm_email.html @@ -0,0 +1,18 @@ + + + + + + Inscription au TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous êtes inscrit au TFJM2 {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é national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..18c187d --- /dev/null +++ b/server_files/services/mail_templates/forgotten_password.html @@ -0,0 +1,20 @@ + + + + + + Mot de passe oublié – TFJM² + + +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é national d'organisation du TFJM2 + + \ 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 new file mode 100644 index 0000000..3e51307 --- /dev/null +++ b/server_files/services/mail_templates/join_team.html @@ -0,0 +1,17 @@ + + + + + Équipe rejointe – TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de rejoindre l'équipe « {TEAM_NAME} » ({TRIGRAM}) pour le TFJM² de {TOURNAMENT_NAME} et nous vous en +remercions.
+
+Cordialement,
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/services/mail_templates/register.html b/server_files/services/mail_templates/register.html new file mode 100644 index 0000000..0334c01 --- /dev/null +++ b/server_files/services/mail_templates/register.html @@ -0,0 +1,16 @@ + + + + + + Inscription au TFJM² {YEAR} + + +Bonjour {FIRST_NAME} {SURNAME},
+
+Vous venez de vous inscrire au TFJM2 {YEAR} et nous vous en remercions.
+Pour valider votre adresse e-mail, veuillez cliquer sur le lien : {URL_BASE}/confirmer_mail/{TOKEN}
+
+Le comité national d'organisation du TFJM2 + + \ No newline at end of file diff --git a/server_files/utils.php b/server_files/utils.php new file mode 100644 index 0000000..e0a26f5 --- /dev/null +++ b/server_files/utils.php @@ -0,0 +1,32 @@ + + 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.

+ + +Erreur : " . $error_message . ""; ?> + +
+ + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ +
+
+ + + diff --git a/server_files/views/ajouter_organisateur.php b/server_files/views/ajouter_organisateur.php new file mode 100644 index 0000000..9709b93 --- /dev/null +++ b/server_files/views/ajouter_organisateur.php @@ -0,0 +1,57 @@ +Erreur : " . $error_message . ""; + } else { + echo "

Organisateur ajouté avec succès ! Ses identifiants ont été transmis par mail.

"; + } +} ?> + +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ +
+
+ + diff --git a/server_files/views/ajouter_tournoi.php b/server_files/views/ajouter_tournoi.php new file mode 100644 index 0000000..9caa95b --- /dev/null +++ b/server_files/views/ajouter_tournoi.php @@ -0,0 +1,127 @@ +Erreur : " . $error_message . ""; + } + else { + echo "

Tournoi de " . htmlspecialchars($_POST["name"]) . " ajouté avec succès !

"; + } +}?> + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + Du au + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ +
+
+ + \ No newline at end of file diff --git a/server_files/views/connexion.php b/server_files/views/connexion.php new file mode 100644 index 0000000..bad0faf --- /dev/null +++ b/server_files/views/connexion.php @@ -0,0 +1,100 @@ +Erreur : " . $error_message . ""; +else { + if (isset($recuperate_account)) + echo "

Le mail de récupération de mot de passe a bien été envoyé.

"; + elseif (isset($reset_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"])) { ?> +
+ + + + + + + + + + +
+ + + +
+ +
+
+user != null) { ?> +
+ + + + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+
+ + +
+ + + + + + + + + + + + + + + + +
+ + Mot de passe oublié ? +
+
+ + + \ No newline at end of file diff --git a/server_files/views/equipe.php b/server_files/views/equipe.php new file mode 100644 index 0000000..af1315c --- /dev/null +++ b/server_files/views/equipe.php @@ -0,0 +1,63 @@ + + +

Informations sur l'équipe

+ + Nom de l'équipe : getName() ?>
+ Trigramme : getTrigram() ?>
+ Tournoi : getName() ?>">getName() ?>
+getEncadrants()[$i - 1] == NULL) + continue; + $encadrant = User::fromId($team->getEncadrants()[$i - 1]); + $id = $encadrant->getId(); + echo "Encadrant $i : getFirstName() . " " . $encadrant->getSurname() . "\">" . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; +} +for ($i = 1; $i <= 6; ++$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() . "
"; +} +if ($team->isSelectedForFinal()) { + $final_name = $FINAL->getName(); + echo "Équipe sélectionnée pour la finale nationale."; +} +?> + +
+ +

Autorisations

+ + + +
+ +
+ +isSelectedForFinal()) { ?> +
+

Autorisations pour la finale

+ +
+ + +
+ + +getValidationStatus() == ValidationStatus::WAITING && $_SESSION["role"] == Role::ADMIN) { ?> +
+ +
+ isSelectedForFinal() && $_SESSION["role"] == Role::ADMIN) { ?> +
+
+ +
+ + + \ No newline at end of file diff --git a/server_files/views/footer.php b/server_files/views/footer.php new file mode 100644 index 0000000..078caa7 --- /dev/null +++ b/server_files/views/footer.php @@ -0,0 +1,6 @@ + + + + + + diff --git a/server_files/views/header.php b/server_files/views/header.php new file mode 100644 index 0000000..f07fee0 --- /dev/null +++ b/server_files/views/header.php @@ -0,0 +1,76 @@ + + + + + + + Site d'inscription pour le TFJM² <?= $YEAR ?> + + + + + + + + + + + + + + + + + + + +
+
+
\ No newline at end of file diff --git a/server_files/views/index.php b/server_files/views/index.php new file mode 100644 index 0000000..b765490 --- /dev/null +++ b/server_files/views/index.php @@ -0,0 +1,127 @@ + + + +
+ + + +
+ +
+

Vous souhaitez participer au tournoi ? Votre équipe est déjà formée ?

+

Créez un compte pour commencer la procédure d'inscription ou + connectez-vous si votre équipe a déjà un compte.

+
+ +
+ +
+

Bienvenue sur le site d'inscription du TFJM2 !

+
+ +
+ Ce site a été conçu pour gérer les inscriptions au Tournoi Français des Jeunes Mathématiciennes et + Mathématiciens. +
+ Cliquez ici pour accéder au site de présentation du tournoi. +
+ +
+ +

+ Attention aux échéances ! Chaque tournoi a une date limite pour les inscriptions et une date limite pour + déposer vos solutions. Elles sont affichées avec les informations de chaque tournoi. Merci de vous y + référer ! +
+ Une fois l'échéance passée, le site bloque tout accès aux inscriptions (et respectivement au dépôt des + solutions).
+

+ +

+ Attention, modification du règlement par rapport aux années précédentes : article 4.3 +
+ "l’équipe doit envoyer par mail à contact@tfjm.org, une lettre (au format pdf), répondant aux questions + suivantes : +
+ +

+
    +
  • Comment l’équipe s’est-elle formée ?
  • +
  • Comment l’équipe va-t-elle travailler (où peut-elle se rencontrer, à quelle fréquence, rencontres avec + l’encadrant•e) ? +
  • +
+ + Cette lettre permettra aux organisateurs•trices de vérifier que l’équipe dispose des conditions nécessaires à + une participation sérieuse. Sont dispensées les équipes dont la moitié ou plus des membres sont scolarisés dans + le même établissement. Le comité National d’Organisation se réserve le droit d’accepter ou non l’inscription des + équipes concernées par cette lettre." +
+ + Pour plus de détail, voir le règlement : https://tfjm.org/infos-tournois/ +

+ +
+

Comment ça marche ?

+
+ +

+ Pour participer à l'un des tournois régionaux, il suffit de créer un compte sur la rubrique + Inscription. Il vous faudra une adresse email pour ce faire. Un mail de confirmation sera envoyé à + cette adresse. Il vous fournira un nom d'utilisateur et un mot de passe que vous allez devoir changer par la + suite. +

+ +

+ Vous pouvez accéder à votre compte via la rubrique Connexion. Une fois connecté, vous pourrez : +

+
    +
  • rentrer des informations sur les membres de votre équipe, tant participants qu'encadrants ;
  • +
  • enregistrer et télécharger des versions préliminaires de vos solutions (seulement la dernière version + enregistrée avant la date limite sera prise en compte pour le tournoi). +
  • +
+ + Une fois que vous aurez fourni toutes les informations demandées dans la rubrique Mon Équipe, votre + inscription pourra être validée par les organisateurs locaux. +

+ + +

+ ATTENTION ! Votre équipe ne sera considérée comme admissible à participer au tournoi que + lorsque cette première étape aura été franchie. +

+ +

+ Pensez donc à former une équipe complète (minimum 4 participants et 1 encadrant) le plus tôt possible pour + avoir plus de chances de participer, compte tenu du nombre des places disponibles dans chaque tournoi (qui + sera dûment affiché sur la rubrique Liste des Tournois). Les équipes restantes seront placées en + liste d'attente. +

+ +

+ Pour les équipes dont l'inscription aura été validée, des documents à télécharger, remplir et signer + deviendront disponibles sur votre compte. Vous allez devoir ensuite les scanner et les télécharger vers le + site pour compléter votre inscription. +

+ + +

+ ATTENTION ! Les équipes qui ne respecteront pas les délais pour rendre ces documents + risquent d'être disqualifiées et de laisser leur place aux équipes placées en liste d'attente. +

+ +

+ NB : Ce site est récent et il est encore possible que certaines pages ne fonctionnent + pas correctement. Si vous remarquez des bugs, merci de les signaler à l'adresse contact@tfjm.org. +

+ +
+ + \ No newline at end of file diff --git a/server_files/views/informations.php b/server_files/views/informations.php new file mode 100644 index 0000000..275f868 --- /dev/null +++ b/server_files/views/informations.php @@ -0,0 +1,44 @@ + + +

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

+ +getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { ?> + Équipe : getTrigram() . "\">" . $team->getName() . " (" . $team->getTrigram() . ")" ?>
+ +Date de naissance : getBirthDate()) ?>
+Sexe : getGender() == "M" ? "Masculin" : "Féminin" ?>
+Adresse : getAddress() . ", " . $user->getPostalCode() . " " . $user->getCity() . ($user->getCountry() == "France" ? "" : ", " . $user->getCountry()) ?>
+Adresse e-mail : getEmail() ?>
+Numéro de téléphone : getPhoneNumber() ?>
+ +getRole() == Role::PARTICIPANT) { ?> + Lycée : getSchool() ?>
+ Classe : getClass()) ?>
+ Nom du responsable légal : getResponsibleName() ?>
+ Numéro de téléphone du responsable légal : getResponsiblePhone() ?>
+ Adresse e-mail du responsable légal : getResponsibleEmail() ?> +getDescription() != "") { ?> + Description : getDescription() ?>
+"; + +if ($user->getRole() == Role::ADMIN || $user->getRole() == Role::ORGANIZER) { + foreach ($tournaments as $tournament) { + echo "Organise le tournoi getName(). "\">" . $tournament->getName() . "
"; + } +} +elseif ($user->getRole() == Role::PARTICIPANT || $user->getRole() == Role::ENCADRANT) { ?> +

Autorisations

+ isSelectedForFinal()) { ?> +
+

Autorisations pour la finale

+ Erreur : " . $error_message . ""; +?> + + + Votre inscription est validée ! Merci désormais de confirmer votre boîte mail pour valider votre adresse. + +

Vous êtes déjà connecté !

+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
/> + />
" required/>
+
+ +
+ +
+
+
+ + + + + + \ No newline at end of file diff --git a/server_files/views/mon_compte.php b/server_files/views/mon_compte.php new file mode 100644 index 0000000..7ddc241 --- /dev/null +++ b/server_files/views/mon_compte.php @@ -0,0 +1,178 @@ +Erreur : " . $error_message . ""; + +elseif (isset($my_account) || isset($new_password)) { + ?> +

Votre compte a bien été mis à jour !

+ getEmail() != $my_account->email) { + echo "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."; + } + ?> + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + getRole() == Role::PARTICIPANT) { ?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
getEmail() ?>
getSurname() ?>
getFirstName() ?>
getBirthDate()) ?>
getGender() == "M") echo "checked" ?> /> + getGender() == "F") echo "checked" ?> />
getAddress() ?>
getPostalCode() ?>
getCity() ?>
getCountry() ?>
getPhoneNumber() ?>
getSchool() ?>
+ + + getResponsibleName() ?> +
+ +
+ + + getResponsiblePhone() ?> +
+ +
+ + + getResponsibleEmail() ?> +
+ +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + +
+
+ + \ No newline at end of file diff --git a/server_files/views/mon_equipe.php b/server_files/views/mon_equipe.php new file mode 100644 index 0000000..b11eb89 --- /dev/null +++ b/server_files/views/mon_equipe.php @@ -0,0 +1,161 @@ +Erreur : " . $error_message . ""; +elseif (isset($send_document)) + echo "

Le fichier a été correctement envoyé !

"; +?> + +

Informations sur l'équipe

+ + Nom de l'équipe : getName() ?>
+ Trigramme : getTrigram() ?>
+ Tournoi : getName() ?>
+getEncadrants()[$i] == NULL) + continue; + $encadrant = User::fromId($team->getEncadrants()[$i - 1]); + $id = $encadrant->getId(); + echo "Encadrant $i : getFirstName() . " " . $encadrant->getSurname() . "\">" . $encadrant->getFirstName() . " " . $encadrant->getSurname() . "
"; +} +for ($i = 1; $i <= 6; ++$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() . "
"; +} +?> + Code d'accès : getAccessCode() ?>
+isSelectedForFinal()) { + $final_name = $FINAL->getName(); + echo "Équipe sélectionnée pour la finale nationale.
"; +} ?> + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ +
+
+ + + + + + Modifier mon équipe + +
+

Mes autorisations

+ isSelectedForFinal()) { ?> +
+

Mes autorisations pour la finale

+ getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+
+ + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+
+ + getValidationStatus() == ValidationStatus::NOT_READY) { ?> +
+ + + + + + + +
+
+ +
+
+
+ +
+
+ + + + \ No newline at end of file diff --git a/server_files/views/rejoindre_equipe.php b/server_files/views/rejoindre_equipe.php new file mode 100644 index 0000000..de638ee --- /dev/null +++ b/server_files/views/rejoindre_equipe.php @@ -0,0 +1,33 @@ + + Vous avez bien rejoint l'équipe getName() ?> ! + + + Erreur : " . $error_message . ""; ?> + +
+ + + + + + + + + + + +
+ + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/server_files/views/solutions.php b/server_files/views/solutions.php new file mode 100644 index 0000000..cb9ae33 --- /dev/null +++ b/server_files/views/solutions.php @@ -0,0 +1,75 @@ +Erreur : " . $error_message . ""; +} elseif (isset($save_solution)) { + echo "

Le fichier a été correctement envoyé !

"; +} +?> + +getSolutionsDate()) { ?> +
+ + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+
+ + +
+ +

Solutions soumises :

+ +getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + echo "Problème $problem (Version $version) : Télécharger
"; +} + +if ($team->isSelectedForFinal()) { ?> +
+ +

Solutions soumises pour la finale :

+ getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + echo "Problème $problem (Version $version) : Télécharger
"; + } +} + +require_once "footer.php"; diff --git a/server_files/views/solutions_orga.php b/server_files/views/solutions_orga.php new file mode 100644 index 0000000..989d719 --- /dev/null +++ b/server_files/views/solutions_orga.php @@ -0,0 +1,25 @@ +Tournoi de " . $tournament->getName() . "\n"; + $sols = $tournament->getAllSolutions(); + /** @var Solution $sol */ + foreach ($sols as $sol) { + $file_id = $sol->getFileId(); + $problem = $sol->getProblem(); + $version = $sol->getVersion(); + $team = Team::fromId($sol->getTeamId()); + $team_name = $team->getName(); + $team_trigram = $team->getTrigram(); + echo "Problème n°$problem de l'équipe $team_name ($team_trigram), version $version : Télécharger
"; + } + + echo "
\n"; + echo "getId() . "\" />\n"; + echo "\n"; + echo "

\n"; +} + +require_once "server_files/views/footer.php"; \ No newline at end of file diff --git a/server_files/views/syntheses.php b/server_files/views/syntheses.php new file mode 100644 index 0000000..fe9edf1 --- /dev/null +++ b/server_files/views/syntheses.php @@ -0,0 +1,79 @@ +getSolutionsDate()) { + echo "

Il est trop tôt pour se préoccuper des notes de synthèse, attendez le tirage des poules.

"; + require_once "server_files/views/footer.php"; +} + +if (isset($error_message)) { + if ($error_message !== false) { + echo "

Erreur : " . $error_message . "

"; + } + else { + echo "

Le fichier a été correctement envoyé !

"; + } +}?> + +getSynthesesDate()) { ?> +
+ + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ +
+
+ + +
+ +

Notes de synthèse soumises :

+ +getFileId(); + $dest = $synthesis->getDest(); + $version = $synthesis->getVersion(); + echo "Note de synthèse pour " . ($dest == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") . " (version $version) : Télécharger
"; +} + +if ($team->isSelectedForFinal()) { ?> +
+ +

Notes de synthèse soumises pour la finale :

+ getFileId(); + $dest = $synthesis->getDest(); + $version = $synthesis->getVersion(); + echo "Note de synthèse pour " . ($dest == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") . " (version $version) : Télécharger
"; + } +} + +require_once "footer.php"; \ No newline at end of file diff --git a/server_files/views/syntheses_orga.php b/server_files/views/syntheses_orga.php new file mode 100644 index 0000000..2912be6 --- /dev/null +++ b/server_files/views/syntheses_orga.php @@ -0,0 +1,27 @@ +Tournoi de " . $tournament->getName() . "\n"; + $syntheses = $tournament->getAllSyntheses(); + /** @var Synthesis $synthesis */ + foreach ($syntheses as $synthesis) { + $file_id = $synthesis->getFileId(); + $dest = $synthesis->getDest(); + $version = $synthesis->getVersion(); + $team = Team::fromId($synthesis->getTeamId()); + $team_name = $team->getName(); + $team_trigram = $team->getTrigram(); + echo "Note de synthèse de l'équipe $team_name ($team_trigram) pour " . ($dest == DestType::OPPOSANT ? "l'opposant" : "le rapporteur") + . ", version $version : Télécharger
"; + } + + echo "
\n"; + echo "getId() . "\" />\n"; + echo "\n"; + echo "

\n"; +} + +require_once "server_files/views/footer.php"; diff --git a/server_files/views/tournoi.php b/server_files/views/tournoi.php new file mode 100644 index 0000000..e0ebc5c --- /dev/null +++ b/server_files/views/tournoi.php @@ -0,0 +1,220 @@ + + +Erreur : $error_message"; +?> + +

Tournoi de getName() ?>

+ +Organisateur= 2 ? 's' : '' ?> : +getId(); + $orga_name = $orga->getFirstName() . " " . $orga->getSurname(); + if ($_SESSION["role"] == Role::ORGANIZER || $_SESSION["role"] == Role::ADMIN) + $s .= "$orga_name"; + else + $s .= $orga_name; + $s .= ", "; +} +echo substr($s, 0, -2); +?> +
+Nombre d'équipes maximal : getSize() ?>
+Lieu : getPlace() ?>
+Prix par partipant : getPrice() == 0 ? "Gratuit" : $tournament->getPrice() . " €" ?>
+Dates : Du getStartDate()) ?> au getEndDate()) ?>
+Clôture des inscriptions : getInscriptionDate(), true) ?>
+Date limite d'envoi des solutions : getSolutionsDate(), true) ?>
+Date limite d'envoi des notes de synthèse : getSynthesesDate(), true) ?>
+Description : getDescription() ?>
+isFinal()) + echo "Ce tournoi est la finale nationale du TFJM² 2020.
"; +?> + +organize($_SESSION["user_id"]))) { ?> + Éditer le tournoi + + + + +
+ +

Équipes inscrites à ce tournoi :

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Équipe + + Trigramme + + Date d'inscription + + État de validation de l'inscription +
+ organize($_SESSION["user_id"])))) + echo "getTrigram() . "\">" . $team->getName(). ""; + else + echo $team->getName(); + ?> + getTrigram() ?>getInscriptionDate()) ?>getValidationStatus()) ?>
+ Équipe + + Trigramme + + Date d'inscription + + État de validation de l'inscription +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + Du + au +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ +
+
+ + + + diff --git a/server_files/views/tournois.php b/server_files/views/tournois.php new file mode 100644 index 0000000..e631025 --- /dev/null +++ b/server_files/views/tournois.php @@ -0,0 +1,41 @@ + + +

Liste des tournois

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NomDatesInscription avant leDate de rendu des solutionsPlaces disponibles
getName() ?>Du getStartDate()) ?> au getEndDate()) ?>getSolutionsDate()) ?>getSynthesesDate()) ?>getSize() ?>
NomDatesInscription avant leDate de rendu des solutionsPlaces disponibles
+ + diff --git a/setup/create_database.sql b/setup/create_database.sql new file mode 100644 index 0000000..d885d4f --- /dev/null +++ b/setup/create_database.sql @@ -0,0 +1,184 @@ +-- phpMyAdmin SQL Dump +-- version 4.6.6deb4 +-- https://www.phpmyadmin.net/ +-- +-- Client : localhost:3306 +-- Généré le : Dim 08 Septembre 2019 à 19:00 +-- Version du serveur : 10.3.15-MariaDB-1 +-- Version de PHP : 7.3.4-2 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+02: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 : `tfjm` +-- +CREATE DATABASE IF NOT EXISTS `inscription-tfjm` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +USE `inscription-tfjm`; + +-- -------------------------------------------------------- + +-- +-- 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, + `tournament` int(11) NOT NULL, + `type` varchar(64) NOT NULL, + `uploaded_at` datetime NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`file_id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +-- -------------------------------------------------------- + +-- +-- Structure de la table `organizers` +-- + +CREATE TABLE IF NOT EXISTS `organizers` +( + `id` int(11) NOT NULL AUTO_INCREMENT, + `organizer` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +-- -------------------------------------------------------- + +-- +-- Structure de la table `solutions` +-- + +CREATE TABLE IF NOT EXISTS `solutions` +( + `file_id` varchar(64) NOT NULL, + `team` int(11) NOT NULL, + `tournament` 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 `syntheses` +-- + +CREATE TABLE IF NOT EXISTS `syntheses` +( + `file_id` varchar(64) NOT NULL, + `team` int(11) NOT NULL, + `tournament` int(11) NOT NULL, + `dest` varchar(64) NOT NULL, + `uploaded_at` datetime NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`file_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, + `tournament` int(8) NOT NULL, + `encadrant_1` int(8) DEFAULT NULL, + `encadrant_2` 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, + `participant_6` int(8) DEFAULT NULL, + `inscription_date` timestamp NOT NULL DEFAULT current_timestamp(), + `validation_status` varchar(64) NOT NULL, + `final_selection` tinyint(1) NOT NULL DEFAULT 0, + `access_code` varchar(6) NOT NULL, + `year` int(4) NOT NULL, + PRIMARY KEY (`id`) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8; + +-- -------------------------------------------------------- + +-- +-- Structure de la table `tournaments` +-- + +CREATE TABLE IF NOT EXISTS `tournaments` +( + `id` int(8) NOT NULL AUTO_INCREMENT, + `name` varchar(64) NOT NULL, + `size` int(1) NOT NULL, + `place` varchar(255) NOT NULL, + `price` int(4) NOT NULL, + `description` varchar(255) NOT NULL, + `date_start` date NOT NULL, + `date_end` date NOT NULL, + `date_inscription` datetime NOT NULL, + `date_solutions` datetime NOT NULL, + `date_syntheses` datetime NOT NULL, + `final` tinyint(1) NOT NULL DEFAULT 0, + `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, + `birth_date` date DEFAULT NULL, + `gender` char(1) DEFAULT NULL, + `address` varchar(255) DEFAULT NULL, + `postal_code` int(5) DEFAULT NULL, + `city` varchar(255) DEFAULT NULL, + `country` varchar(255) DEFAULT 'France', + `phone_number` varchar(20) DEFAULT NULL, + `school` varchar(255) DEFAULT NULL, + `class` varchar(255) DEFAULT NULL, + `responsible_name` varchar(255) DEFAULT NULL, + `responsible_phone` varchar(20) DEFAULT NULL, + `responsible_email` varchar(255) DEFAULT NULL, + `description` varchar(255) DEFAULT NULL, + `role` varchar(64) NOT NULL, + `team_id` int(8) DEFAULT NULL, + `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; + +/*!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 new file mode 100644 index 0000000..3a3cc60 --- /dev/null +++ b/setup/msmtprc @@ -0,0 +1,18 @@ +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 tfjm +host ssl0.ovh.net +auth on +port 465 +from contact@tfjm.org +user contact@tfjm.org +passwordeval "echo $TFJM_MAIL_PASSWORD" + +# Set a default account +account default : tfjm