diff --git a/API_Interfaces.txt b/API_Interfaces.txt index 9a73149..b5a9ad7 100644 --- a/API_Interfaces.txt +++ b/API_Interfaces.txt @@ -1,7 +1,10 @@ ####################### LoginAPI (api/login) ####################### -GET -> Authentication method +POST -> Authentication method + In: + email = Email and login of the user (must be unique) + password = Password of the user (secured by HTTPS) Out: 200 -> AUTH_RESULT = "OK" : Authentication sucessful 401 -> AUTH_RESULT = "AUTHENTICATION_FAILURE" : Wrong login/password @@ -20,6 +23,7 @@ GET -> Get the current logged user, return None if no one is connected Out: 200 -> USER = |null : Dictionary containing user infos or null + ######################## UserAPI (api/user) ######################## @@ -27,6 +31,7 @@ POST -> Create a user if it not already exists In: email = Email and login of the user (must be unique) role = Role of the user (can be concatenated with -) 1=secrétaire, 2=resp_formation, 3=tuteur_univ, 4=étudiant, 5=tuteur_ent + name = Display name of the user Out: 200 -> UID = : The user already exists with the id USER_ID 201 -> UID = : The user has been successfully created with the id USER_ID @@ -48,6 +53,7 @@ GET -> Getting specified user infos Out: 200 -> USER = |null : Dictionary containing user infos or null + ######################## GroupAPI (api/group) ######################## @@ -98,3 +104,92 @@ OPTIONS -> Add pairs of users (student/tutor) to the group 400 -> ERROR = "A student can't be a tutor !" : The given USER_ID for tutor have the "student" role (4) and so can't be a tutor 405 -> ERROR = "This group doesn't exists !" : Bad GROUP_ID provided 409 -> ERROR = "Pairs are incorrectly formed !" : Bad syntax in pairs table + + +######################## +LivretAPI (api/livret) +######################## +POST -> Create a livret if it not already exists + In: + group_id = Id of the group where this livret should be inserted in (we must have only one livret per student in a single group) + etutor_id = UID of the company tutor + company_name = Name of the company + company_address = Mail address of the company + contract_type = Type of the internship contract (1 = contrat d'alternance, 2 = contrat de professionnalisation, 3 = stage) + contract_start = Date of the contract's beginning (format : dd-mm-yyyy) + contract_end = Date of the contract's end (format : dd-mm-yyyy) + description = Description of the internship missions and activities overview + Out: + 200 -> LID = : The livret already exists with the id LIVRET_ID + 201 -> LID = : The livret has been successfully created with the id LIVRET_ID + 400 -> ERROR = "One or more parameters are missing" : Bad request + 400 -> ERROR = "The user with id doesn't exists !" : The given USER_ID for etutor is not found + 400 -> ERROR = "An etutor must have the 'etutor' role !" : The given USER_ID for etutor doesn't have the "etutor" role (5) + 400 -> ERROR = "The contract start can't be after its end !" : The given contract's end date is anterior to it's beginning + 405 -> ERROR = "The group with id GROUP_ID doesn't exists !" : The given GROUP_ID is not found + 405 -> ERROR = "The The current student is not registered in the group !" : The currently logged student is not affected to the specified GROUP_ID + +PUT -> Modify an existing livret + In: (Suffix = /bylid/) + etutor_id = UID of the company tutor + company_name = Name of the company + company_address = Mail address of the company + contract_type = Type of the internship contract (1 = contrat d'alternance, 2 = contrat de professionnalisation, 3 = stage) + contract_start = Date of the contract's beginning (format : dd-mm-yyyy) + contract_end = Date of the contract's end (format : dd-mm-yyyy) + description = Description of the internship missions and activities overview + Out: + 200 -> LID = : The livret has been modified successfully with the id LIVRET_ID + 400 -> ERROR = "One or more parameters are missing !" : Bad request + 400 -> ERROR = "The user with id doesn't exists !" : The given USER_ID for etutor is not found + 400 -> ERROR = "An etutor must have the 'etutor' role !" : The given USER_ID for etutor doesn't have the "etutor" role (5) + 400 -> ERROR = "The contract start can't be after its end !" : The given contract's end date is anterior to it's beginning + 405 -> ERROR = "This group doesn't exists !" : Bad LIVRET_ID provided + +GET -> Getting specified livret infos + In: (Suffixes = /bylid/ | /bytutorship// ) + Out: + 200 -> LIVRET = |null : Dictionary containing livret infos or null + + +######################## +PeriodAPI (api/period) +######################## +POST -> Create a period for all livrets in a group + In: + group_id = Id of the group where this period should be inserted in + period_type = Type of the period (1 = universitaire, 2 = entreprise) + start = Date of the period's beginning (format : dd-mm-yyyy) + end = Date of the period's end (format : dd-mm-yyyy) + Out: + 200 -> RESULT = OK : The period has been successfully created in all the livrets in the given group + 400 -> ERROR = "One or more parameters are missing" : Bad request + 401 -> ERROR = "UNAUTHORIZED" : The current user is not allowed to modify this group (only the group's resp can do it) + 400 -> ERROR = "The period's start can't be after its end !" : The given period's end date is anterior to it's beginning + 405 -> ERROR = "The group with id GROUP_ID doesn't exists !" : The given GROUP_ID is not found + +PUT -> Add the comments of a user in an existing period + In: (Suffix = /bypid/) + text = Comment added by the user about the period (student or etutor) + Out: + 200 -> PID = : The period has been modified successfully with the id PERIOD_ID + 400 -> ERROR = "One or more parameters are missing !" : Bad request + 400 -> ERROR = "This period doesn't exists !" : Bad PERIOD_ID provided + 401 -> ERROR = "UNAUTHORIZED" : The current user is not allowed to modify this group (only the student and his etutor can do it) + 405 -> ERROR = "A tutor can't modify a university period !" : A tutor can't modify a university period :) + +GET -> Getting specified period infos + In: (Suffix = /bypid/) + Out: + 200 -> PERIOD = |null : Dictionary containing period infos or null + + +######################## +GetAllAPI (api/getAll) +######################## +GET -> Getting specified period infos + In: (Suffix = //) + Parameters for / : + periodsOfLivret/ : Returns all the periods associated to the given + Out: + 200 -> RESULT = \ No newline at end of file diff --git a/Template_PDF/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom.pdf b/Template_PDF/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom.pdf index 18226d5..bb47f6d 100644 Binary files a/Template_PDF/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom.pdf and b/Template_PDF/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom.pdf differ diff --git a/Template_PDF/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom.pdf b/Template_PDF/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom.pdf index 0c9b3f0..9f76fd1 100644 Binary files a/Template_PDF/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom.pdf and b/Template_PDF/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom.pdf differ diff --git a/Template_PDF/LivretAlternant_Accueil_Page4_PosteOccupe_NOM_Prenom.pdf b/Template_PDF/LivretAlternant_Accueil_Page4_PosteOccupe_NOM_Prenom.pdf index c236e5f..e928554 100644 Binary files a/Template_PDF/LivretAlternant_Accueil_Page4_PosteOccupe_NOM_Prenom.pdf and b/Template_PDF/LivretAlternant_Accueil_Page4_PosteOccupe_NOM_Prenom.pdf differ diff --git a/Template_PDF/LivretAlternant_PEntreprise_Bilan_NOM_Prenom.pdf b/Template_PDF/LivretAlternant_PEntreprise_Bilan_NOM_Prenom.pdf index 091741b..c752d3b 100644 Binary files a/Template_PDF/LivretAlternant_PEntreprise_Bilan_NOM_Prenom.pdf and b/Template_PDF/LivretAlternant_PEntreprise_Bilan_NOM_Prenom.pdf differ diff --git a/Template_PDF/LivretAlternant_PFormation_Bis_Bilan_NOM_Prenom.pdf b/Template_PDF/LivretAlternant_PFormation_Bis_Bilan_NOM_Prenom.pdf index 7bc03ce..fef539d 100644 Binary files a/Template_PDF/LivretAlternant_PFormation_Bis_Bilan_NOM_Prenom.pdf and b/Template_PDF/LivretAlternant_PFormation_Bis_Bilan_NOM_Prenom.pdf differ diff --git a/Template_PDF/backup/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom_backup.pdf b/Template_PDF/backup/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom_backup.pdf index 2aec054..11b5577 100644 Binary files a/Template_PDF/backup/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom_backup.pdf and b/Template_PDF/backup/LivretAlternant_Accueil_Page1_Couverture_NOM_Prenom_backup.pdf differ diff --git a/Template_PDF/backup/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom_backup.pdf b/Template_PDF/backup/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom_backup.pdf index 84e6d6e..0c9b3f0 100644 Binary files a/Template_PDF/backup/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom_backup.pdf and b/Template_PDF/backup/LivretAlternant_Accueil_Page2_Sommaire_FicheRenseignements_NOM_Prenom_backup.pdf differ diff --git a/Template_PDF/specification_template.txt b/Template_PDF/specification_template.txt index 4b8d9fa..14443c7 100644 --- a/Template_PDF/specification_template.txt +++ b/Template_PDF/specification_template.txt @@ -1,67 +1,67 @@ Page 1 : -MASTER : {{ nom_master }} +MASTER : {{page1.nom_master }} -{{ nom_complet_master }} +{{ page1.nom_complet_master }} Année universitaire : -{{ annee_1 }} +{{ page1.annee_1 }} - -{{ annee_2 }} +{{ page1.annee_2 }} -De : {{ nom_prenom }} +De : {{ page1.nom_prenom }} -mail : {{ email }} +mail : {{ page1.email }} -tel : {{ telephone }} +tel : {{ page1.telephone }} -Alternant à : {{ entreprise }} +Alternant à : {{ page1.entreprise }} -tuteur/tutrice pédagogique : {{ tuteur_pedagogique }} +tuteur/tutrice pédagogique : {{ page1.tuteur_pedagogique }} -Tuteur / Tutrice entreprise : {{ tuteur_entreprise }} +Tuteur / Tutrice entreprise : {{ page1.tuteur_entreprise }} Page 2 : Alternant Type de contrat : -{{ type_contrat_apprentissage | X }} -{{ type_contrat_professionnalisation | X }} -{{ type_contrat_stage | X }} +{{ page2.type_contrat_apprentissage | X }} +{{ page2.type_contrat_professionnalisation | X }} +{{ page2.type_contrat_stage | X }} -Début de contrat : {{ debut_contrat }} -Fin de contrat : {{ fin_contrat }} -tel : {{ telephone }} -mail : {{ email }} -compostant de formation : {{ compostant_formation }} -responsable tuteur_pedagogique de la formation : {{ responsable_pedagogique_formation }} -tel : {{ tel_responsable_pedagogique_formation }} -mail : {{ mail_responsable_pedagogique_formation }} +Début de contrat : {{ page2.debut_contrat }} +Fin de contrat : {{ page2.fin_contrat }} +tel : {{ page2.telephone }} +mail : {{ page2.email }} +compostant de formation : {{ page2.compostant_formation }} +responsable tuteur_pedagogique de la formation : {{ page2.responsable_pedagogique_formation }} +tel : {{ page2.tel_responsable_pedagogique_formation }} +mail : {{ page2.mail_responsable_pedagogique_formation }} tuteur pédagogique : -{{ tel_tuteur_pedagogique }} -{{ mail_tuteur_pedagogique }} +{{ page2.tel_tuteur_pedagogique }} +{{ page2.mail_tuteur_pedagogique }} tuteur entreprise : -{{ tuteur_entreprise }} -entreprise : {{ entreprise }} -adresse lieu Alternance : {{ adresse_entreprise }} -tel : {{ tel_tuteur_entreprise }} -mail : {{ mail_tuteur_entreprise }} +{{ page2.tuteur_entreprise }} +entreprise : {{ page2.entreprise }} +adresse lieu Alternance : {{ page2.adresse_entreprise }} +tel : {{ page2.tel_tuteur_entreprise }} +mail : {{ page2.mail_tuteur_entreprise }} Page 4 : -poste occupé : {{ poste_occupe }} -{{ poste_occupe_2 }} +poste occupé : {{ page4.poste_occupe }} +{{ page4.poste_occupe_2 }} Pentreprise : -{{ n_periode }} -{{ debut_periode }} -{{ fin_periode }} -{{ travaux_entreprise }} -{{ remarque_tuteur }} +{{ PEntreprise.n_periode }} +{{ PEntreprise.debut_periode }} +{{ PEntreprise.fin_periode }} +{{ PEntreprise.travaux_entreprise }} +{{ PEntreprise.remarque_tuteur }} bilan_periode : -{{ n_periode }} -{{ bilan_periode }} +{{ PFormation.n_periode }} +{{ PFormation.bilan_periode }} diff --git a/backend/OLA.mysql b/backend/OLA.mysql index 79529a8..80d8b2c 100644 --- a/backend/OLA.mysql +++ b/backend/OLA.mysql @@ -66,6 +66,7 @@ CREATE TABLE IF NOT EXISTS LIVRET contract_type INT NOT NULL, contract_start DATE NOT NULL, contract_end DATE NOT NULL, + description TEXT NOT NULL, ressources_dir VARCHAR(512), opened TINYINT(1) NOT NULL, expire DATE NOT NULL, @@ -143,3 +144,5 @@ CREATE UNIQUE INDEX user_email ON `USER` (`email`); CREATE UNIQUE INDEX user_hash ON `USER` (`hash`); +CREATE UNIQUE INDEX tutorship_unique_bygroup + ON `TUTORSHIP` (`group_id`, `student_id`); diff --git a/backend/OLA_DATA.mysql b/backend/OLA_DATA.mysql index 7c8db3a..ed16388 100644 --- a/backend/OLA_DATA.mysql +++ b/backend/OLA_DATA.mysql @@ -1,7 +1,7 @@ USE OLA; INSERT INTO SETTINGS VALUES ('BASE_DIRECTORY', '/OLA_RESSOURCES/', 'Répertoire base pour le dépot des fichiers'); INSERT INTO SETTINGS VALUES ('TEMPLATES_DIRECTORY', '/OLA_TEMPLATES/', 'Répertoire base pour le dépot des fichiers'); -INSERT INTO SETTINGS VALUES ('OLA_URL', 'ola.univ-tlse2.fr/', 'URL de l application'); +INSERT INTO SETTINGS VALUES ('OLA_URL', 'http://ola.univ-tlse2.fr/', 'URL de l application'); INSERT INTO `USER` VALUES (1, '1', 'sec@univ-tlse2.fr', 'Secrétaire', DEFAULT, 'aZeRtYuIoP', '01.23.45.67.89'); INSERT INTO `USER` VALUES (2, '4', 'etu1@univ-tlse2.fr', 'Etudiant 1', DEFAULT, 'qSdFgHjKlM', '01.23.45.67.89'); diff --git a/backend/app/OLA_DATA.mysql b/backend/app/OLA_DATA.mysql deleted file mode 100644 index 1daf4d5..0000000 --- a/backend/app/OLA_DATA.mysql +++ /dev/null @@ -1,18 +0,0 @@ -USE OLA; -INSERT INTO SETTINGS VALUES ('URL_BASE_DIRECTORY', '/OLA_RESSOURCES/', 'Répertoire base pour le dépot des fichiers'); -INSERT INTO SETTINGS VALUES ('OLA_URL', 'ola.univ-tlse2.fr/', 'URL de l application'); - -INSERT INTO `USER` VALUES (1, 'sec', '1', 'sec@univ-tlse2.fr', '01.23.45.67.89'); -INSERT INTO `USER` VALUES (2, 'etu1', '4', 'etu1@univ-tlse2.fr', '01.23.45.67.89'); -INSERT INTO `USER` VALUES (3, 'etu2', '4', 'etu2@univ-tlse2.fr', '01.23.45.67.89'); -INSERT INTO `USER` VALUES (4, 'etu3', '4', 'etu3@univ-tlse2.fr', '01.23.45.67.89'); -INSERT INTO `USER` VALUES (5, 'resp', '2-3', 'resp@univ-tlse2.fr', '01.23.45.67.89'); -INSERT INTO `USER` VALUES (6, 'tut', '3', 'tut@univ-tlse2.fr', '01.23.45.67.89'); - -INSERT INTO `GROUP` VALUES (1, 'M2_ICE_2016-2017_TEST', '2017', 'Master2 ICE', 'Master 2 Informatique Collaborative en Entreprise', 'Sciences du chômage proffessionnel', 5, 1, '/home/dan/PycharmProjects/OLA/backend/app/OLA_RESSOURCES/M2_ICE_2016-2017_TEST'); -INSERT INTO `GROUP` VALUES (2, 'M1_ICE_2016-2017_TEST', '2017', 'Master1 ICE', 'Master 1 Informatique Collaborative en Entreprise', 'Sciences du chômage proffessionnel', 5, 1, '/home/dan/PycharmProjects/OLA/backend/app/OLA_RESSOURCES/M1_ICE_2016-2017_TEST'); - -INSERT INTO TUTORSHIP VALUES (DEFAULT, 1, 2, 5); -INSERT INTO TUTORSHIP VALUES (DEFAULT, 2, 4, 5); -INSERT INTO TUTORSHIP VALUES (DEFAULT, 1, 3, 6); - diff --git a/backend/app/api/ExportPdfAPI.py b/backend/app/api/ExportPdfAPI.py new file mode 100644 index 0000000..4646195 --- /dev/null +++ b/backend/app/api/ExportPdfAPI.py @@ -0,0 +1,82 @@ +from flask_restful import Resource + +from app.model import * +from app.tools.LibPdf import fusion_fichiers + + +class ExportPdfAPI(Resource): + def get(self, uid=0, gid=0, name=""): + if uid > 0: + + user = getUser(uid=uid) + + group = getGroup(gid) + + if user is None: + return {"ERROR": "The user with id " + str(gid) + " does not exists !"}, 400 + + prenom = user["name"].split(" ", 1) + nom = user["name"].split(" ", 2) + + group["name"] + + annee1 = group["year"] + annee2 = int(group["year"]) + 1 + promo = group["class_short"] + + group["class_long"] + group["departement"] + group["resp_id"] + group["sec_id"] + group["ressources_dir"] + + self.data = { + 'page1.nom_master': 'Renan', + 'page1.nom_complet_master': 'Husson', + 'page1.annee_1': 'Husson', + 'page1.annee_2': 'Jean Jaures', + 'page1.nom_prenom': 'Panda', + 'page1.email': 'Panda', + 'page1.telephone': 'Panda', + 'page1.entreprise': 'Panda', + 'page1.tuteur_pedagogique': 'Panda', + 'page1.tuteur_entreprise': 'Panda', + 'page2.type_contrat_apprentissage': True, + 'page2.type_contrat_professionnalisation': True, + 'page2.type_contrat_stage': True, + 'page2.debut_contrat': 'Panda', + 'page2.fin_contrat': 'Panda', + 'page2.telephone': 'Panda', + 'page2.email': 'Panda', + 'page2.compostant_formation': 'Panda', + 'page2.responsable_pedagogique_formation': 'Panda', + 'page2.tel_responsable_pedagogique_formation': 'Panda', + 'page2.mail_responsable_pedagogique_formation': 'Panda', + 'page2.tel_tuteur_pedagogique': 'Panda', + 'page2.mail_tuteur_pedagogique': 'Panda', + 'page2.tuteur_entreprise': 'Panda', + 'page2.entreprise': 'Panda', + 'page2.adresse_entreprise': 'Panda', + 'page2.tel_tuteur_entreprise': 'Panda', + 'page2.mail_tuteur_entreprise': 'Panda', + 'page4.poste_occupe': 'Panda', + 'page4.poste_occupe_2': 'Panda', + 'PEntreprise.n_periode': 'Panda', + 'PEntreprise.debut_periode': 'Panda', + 'PEntreprise.fin_periode': 'Panda', + 'PEntreprise.travaux_entreprise': 'Panda', + 'PEntreprise.remarque_tuteur': 'Panda', + 'pagePFormation.n_periode': 'Panda', + 'pagePFormation.bilan_periode': 'Panda', + + } + + pdf_fusion = ["/page1.pdf", "/page2.pdf"] + chemin_pdf = "/tmp" + + nom_pdf = "Livret_Alternant_BOB_Armandeau.pdf" + + fusion_fichiers(chemin_pdf, nom_pdf, pdf_fusion) + + # Prenom NOM + # remplir_template() diff --git a/backend/app/api/GetAllAPI.py b/backend/app/api/GetAllAPI.py new file mode 100644 index 0000000..9811d6d --- /dev/null +++ b/backend/app/api/GetAllAPI.py @@ -0,0 +1,31 @@ +from flask import session +from flask_restful import Resource + +from app.api.LoginAPI import login_required +from app.model import getLivret, PERIOD, getPeriod + + +class GetAllAPI(Resource): + """ + GetAll Api Resource + Renvoie toutes les occurences correspondant à un critère + """ + + @login_required() + def get(self, what, value): + user = session.get("user") + result = [] + + if what == "periodsOfLivret": # Toutes les périodes associées à un livret + if value > 0: + livret = getLivret(lid=value) + if livret is None: + return {"ERROR": "This livret doesn't exists !"}, 405 + query = PERIOD.select(PERIOD.c.livret_id == value) + res = query.execute() + for row in res: + result.append(getPeriod(pid=row.id)) + else: + return {'ERROR': 'Unkown parameter :' + str(what)}, 200 + + return {'RESULT': result}, 200 diff --git a/backend/app/api/GroupAPI.py b/backend/app/api/GroupAPI.py index a8b13c3..781b566 100644 --- a/backend/app/api/GroupAPI.py +++ b/backend/app/api/GroupAPI.py @@ -3,8 +3,9 @@ import os from flask_restful import Resource, request from app.api import mailsModels -from app.model import * -from app.utils import * +from app.api.LoginAPI import login_required +from app.model import Roles, getGroup, getParam, getUser, USER, GROUP, TUTORSHIP +from app.utils import send_mail, checkParams class GroupAPI(Resource): @@ -12,6 +13,7 @@ class GroupAPI(Resource): Group Api Resource """ + @login_required(roles=[Roles.resp_formation]) def post(self): args = request.get_json(cache=False, force=True) if not checkParams(['name', 'year', 'class_short', 'class_long', 'department', 'resp_id', 'sec_id'], args): @@ -47,8 +49,8 @@ class GroupAPI(Resource): "URL": getParam('OLA_URL')}) mails.append((user["email"], mail)) - if "2" not in user['role'].split('-'): - role = user['role'] + "-2" + if str(Roles.resp_formation) not in user['role'].split('-'): + role = user['role'] + "-" + str(Roles.resp_formation) query = USER.update().values(role=role).where(USER.c.id == resp_id) query.execute() @@ -68,8 +70,8 @@ class GroupAPI(Resource): "URL": getParam('OLA_URL')}) mails.append((user["email"], mail)) - if "1" not in user['role'].split('-'): - role = user['role'] + "-1" + if str(Roles.secretaire) not in user['role'].split('-'): + role = user['role'] + "-" + str(Roles.secretaire) query = USER.update().values(role=role).where(USER.c.id == sec_id) query.execute() @@ -85,6 +87,7 @@ class GroupAPI(Resource): return {"GID": res.lastrowid}, 201 + @login_required(roles=Roles.resp_formation) def put(self, gid): args = request.get_json(cache=False, force=True) if not checkParams(['name', 'year', 'class_short', 'class_long', 'department', 'resp_id', 'sec_id'], args): @@ -124,8 +127,8 @@ class GroupAPI(Resource): "URL": getParam('OLA_URL')}) mails.append((user["email"], mail)) - if "2" not in user['role'].split('-'): - role = user['role'] + "-2" + if str(Roles.resp_formation) not in user['role'].split('-'): + role = user['role'] + "-" + str(Roles.resp_formation) query = USER.update().values(role=role).where(USER.c.id == resp_id) query.execute() @@ -145,8 +148,8 @@ class GroupAPI(Resource): "URL": getParam('OLA_URL')}) mails.append((user["email"], mail)) - if "1" not in user['role'].split('-'): - role = user['role'] + "-1" + if str(Roles.secretaire) not in user['role'].split('-'): + role = user['role'] + "-" + str(Roles.secretaire) query = USER.update().values(role=role).where(USER.c.id == sec_id) query.execute() @@ -165,12 +168,14 @@ class GroupAPI(Resource): return {"GID": gid}, 200 + @login_required() def get(self, gid=0, name=""): if gid > 0: return {'GROUP': getGroup(gid=gid)}, 200 elif name != "": return {'GROUP': getGroup(name=name)}, 200 + @login_required(roles=Roles.resp_formation) def options(self, gid): args = request.get_json(cache=False, force=True) if not checkParams(['pairs'], args): @@ -187,16 +192,16 @@ class GroupAPI(Resource): stud = getUser(uid=p[0]) if stud is None: return {"ERROR": "The user with id " + str(p[0]) + " does not exists !"}, 400 - elif stud['role'] != "4": + elif stud['role'] != str(Roles.etudiant): return {"ERROR": "A student must have the 'student' role !"}, 400 tutor = getUser(uid=p[1]) if tutor is None: return {"ERROR": "The user with id " + str(p[1]) + " does not exists !"}, 400 - elif tutor['role'] == "4": + elif tutor['role'] == str(Roles.etudiant): return {"ERROR": "A student can't be a tutor !"}, 400 elif "3" not in tutor['role'].split('-'): - role = tutor['role'] + "-3" + role = tutor['role'] + "-" + str(Roles.tuteur_univ) query = USER.update().values(role=role).where(USER.c.id == p[1]) query.execute() except IndexError: diff --git a/backend/app/api/LivretAPI.py b/backend/app/api/LivretAPI.py index ecd87cd..4ce7d3a 100644 --- a/backend/app/api/LivretAPI.py +++ b/backend/app/api/LivretAPI.py @@ -1,10 +1,13 @@ import os +from datetime import datetime, timedelta +from flask import session from flask_restful import Resource, request from app.api import mailsModels -from app.model import * -from app.utils import * +from app.api.LoginAPI import login_required +from app.model import Roles, getParam, getGroup, getUser, USER, LIVRET, getLivret, getTutorship +from app.utils import send_mail, checkParams class LivretAPI(Resource): @@ -12,69 +15,73 @@ class LivretAPI(Resource): Livret Api Resource """ + @login_required(roles=[Roles.etudiant]) def post(self): args = request.get_json(cache=False, force=True) - if not checkParams(['name', 'year', 'class_short', 'class_long', 'department', 'resp_id', 'sec_id'], args): + if not checkParams(['group_id', 'etutor_id', 'company_name', 'company_address', 'contract_type', + 'contract_start', 'contract_end', 'description'], args): return {"ERROR": "One or more parameters are missing !"}, 400 - name = args['name'] - year = args['year'] - class_short = args['class_short'] - class_long = args['class_long'] - department = args['department'] - resp_id = args['resp_id'] - sec_id = args['sec_id'] - res_dir = getParam('BASE_DIRECTORY') + name + "/" + user = session.get("user") + group_id = args['group_id'] + etutor_id = args['etutor_id'] + company_name = args['company_name'] + company_address = args['company_address'] + contract_type = int(args['contract_type']) + contract_start = datetime.strptime(args['contract_start'], "%d-%m-%Y") + contract_end = datetime.strptime(args['contract_end'], "%d-%m-%Y") + description = args['description'] mails = [] - group = getGroup(name=name) - if group is not None: - return {"GID": group["id"]}, 200 + group = getGroup(gid=group_id) + if group is None: + return {"ERROR": "This group with id " + str(group_id) + "does not exists !"}, 405 - user = getUser(uid=resp_id) - if user is None: - return {"ERROR": "The user with id " + str(resp_id) + " does not exists !"}, 400 + tutorship = getTutorship(gid=group_id, student=user["id"]) + + if tutorship is None: + return {"ERROR": "The current student is not registered in the group" + str(group_id) + " !"}, 405 + + tutorship_id = tutorship["id"] + + livret = getLivret(group_id=group_id, student_id=user["id"]) + if livret is not None: + return {"LID": livret["id"]}, 200 + + # On vérifie que l'utilisateur actuel a le droit de modifier ce livret + if user["id"] != livret["tutorship_id"]["student_id"]: + return {"ERROR": "UNAUTHORIZED"}, 401 + + user2 = getUser(uid=etutor_id) + if user2 is None: + return {"ERROR": "The user with id " + str(etutor_id) + " does not exists !"}, 400 else: - query = USER.select(USER.c.id == user["id"]) + query = USER.select(USER.c.id == user2["id"]) rows = query.execute() res = rows.first() if res.hash is not None and len(res.hash) > 0: - mail = mailsModels.getMailContent("NEW_RESP_OF_GROUP", {"GROUP": name, - "URL": getParam('OLA_URL') + "registration/" - + res.hash}) - else: - mail = mailsModels.getMailContent("RESP_OF_GROUP", {"GROUP": name, - "URL": getParam('OLA_URL')}) - - mails.append((user["email"], mail)) - if "2" not in user['role'].split('-'): - role = user['role'] + "-2" - query = USER.update().values(role=role).where(USER.c.id == resp_id) - query.execute() - - user = getUser(uid=sec_id) - if user is None: - return {"ERROR": "The user with id " + str(sec_id) + " does not exists !"}, 400 - else: - query = USER.select(USER.c.id == user["id"]) - rows = query.execute() - res = rows.first() - if res.hash is not None and len(res.hash) > 0: - mail = mailsModels.getMailContent("NEW_SEC_OF_GROUP", {"GROUP": name, + mail = mailsModels.getMailContent("NEW_ETUTOR_ADDED", {"GROUPE": group["name"], "URL": getParam('OLA_URL') + "registration/" + res.hash}) else: - mail = mailsModels.getMailContent("SEC_OF_GROUP", {"GROUP": name, + mail = mailsModels.getMailContent("ETUTOR_ADDED", {"GROUPE": group["name"], "URL": getParam('OLA_URL')}) - mails.append((user["email"], mail)) - if "1" not in user['role'].split('-'): - role = user['role'] + "-1" - query = USER.update().values(role=role).where(USER.c.id == sec_id) - query.execute() + mails.append((user2["email"], mail)) + if str(Roles.tuteur_entreprise) not in user2['role'].split('-'): + return {"ERROR": "The user with id " + str(etutor_id) + + " doesn't have the 'etutor' role (" + str(Roles.tuteur_entreprise) + ") !"}, 400 - query = GROUP.insert().values(name=name, year=year, class_short=class_short, class_long=class_long, - department=department, resp_id=resp_id, sec_id=sec_id, ressources_dir=res_dir) + if contract_start > contract_end: + return {"ERROR": "The contract start can't be after its end !"}, 400 + + res_dir = group["ressources_dir"] + "/" + str(user['id']) + "/" + expire = datetime.now() + timedelta(days=365) + + query = LIVRET.insert().values(tutorship_id=tutorship_id, etutor_id=etutor_id, company_name=company_name, + company_address=company_address, contract_type=contract_type, + contract_start=contract_start, contract_end=contract_end, + description=description, ressources_dir=res_dir, opened='1', expire=expire) res = query.execute() os.mkdir(res_dir) @@ -83,139 +90,74 @@ class LivretAPI(Resource): mail = m[1] send_mail(mail[0], addr, mail[1]) - return {"GID": res.lastrowid}, 201 + return {"LID": res.lastrowid}, 201 - def put(self, gid): + @login_required(roles=[Roles.etudiant]) + def put(self, lid): args = request.get_json(cache=False, force=True) - if not checkParams(['name', 'year', 'class_short', 'class_long', 'department', 'resp_id', 'sec_id'], args): + if not checkParams(['etutor_id', 'company_name', 'company_address', 'contract_type', + 'contract_start', 'contract_end', 'description'], args): return {"ERROR": "One or more parameters are missing !"}, 400 - name = args['name'].replace(" ", "_").replace("/", "-") - year = args['year'] - class_short = args['class_short'] - class_long = args['class_long'] - department = args['department'] - resp_id = args['resp_id'] - sec_id = args['sec_id'] - res_dir = getParam('BASE_DIRECTORY') + name + "/" + etutor_id = args['etutor_id'] + company_name = args['company_name'] + company_address = args['company_address'] + contract_type = int(args['contract_type']) + contract_start = datetime.strptime(args['contract_start'], "%d-%m-%Y") + contract_end = datetime.strptime(args['contract_end'], "%d-%m-%Y") + description = args['description'] mails = [] - group = getGroup(gid=gid) - if group is None: - return {"ERROR": "This group does not exists !"}, 405 + livret = getLivret(lid=lid) + if livret is None: + return {"ERROR": "This livret does not exists !"}, 405 - group2 = getGroup(name=name) - if group2 is not None: - return {"ERROR": "A group with this name already exists !"}, 405 + # On vérifie que l'utilisateur actuel a le droit de modifier ce livret + user = session.get("user") + if user["id"] != livret["tutorship_id"]["student_id"]: + return {"ERROR": "UNAUTHORIZED"}, 401 - user = getUser(uid=resp_id) + user = getUser(uid=etutor_id) if user is None: - return {"ERROR": "The user with id " + str(resp_id) + " does not exists !"}, 400 + return {"ERROR": "The user with id " + str(etutor_id) + " does not exists !"}, 400 else: query = USER.select(USER.c.id == user["id"]) rows = query.execute() res = rows.first() if res.hash is not None and len(res.hash) > 0: - mail = mailsModels.getMailContent("NEW_RESP_OF_GROUP", {"GROUP": group["name"], - "URL": getParam('OLA_URL') + "registration/" - + res.hash}) + mail = mailsModels.getMailContent("NEW_ETUTOR_ADDED", + {"GROUPE": livret["tutorship_id"]["group_id"]["name"], + "URL": getParam('OLA_URL') + "registration/" + + res.hash}) else: - mail = mailsModels.getMailContent("RESP_OF_GROUP", {"GROUP": group["name"], - "URL": getParam('OLA_URL')}) - - mails.append((user["email"], mail)) - if "2" not in user['role'].split('-'): - role = user['role'] + "-2" - query = USER.update().values(role=role).where(USER.c.id == resp_id) - query.execute() - - user = getUser(uid=sec_id) - if user is None: - return {"ERROR": "The user with id " + str(sec_id) + " does not exists !"}, 400 - else: - query = USER.select(USER.c.id == user["id"]) - rows = query.execute() - res = rows.first() - if res.hash is not None and len(res.hash) > 0: - mail = mailsModels.getMailContent("NEW_SEC_OF_GROUP", {"GROUP": group["name"], - "URL": getParam('OLA_URL') + "registration/" - + res.hash}) - else: - mail = mailsModels.getMailContent("SEC_OF_GROUP", {"GROUP": group["name"], + mail = mailsModels.getMailContent("ETUTOR_ADDED", {"GROUPE": livret["tutorship_id"]["group_id"]["name"], "URL": getParam('OLA_URL')}) mails.append((user["email"], mail)) - if "1" not in user['role'].split('-'): - role = user['role'] + "-1" - query = USER.update().values(role=role).where(USER.c.id == sec_id) - query.execute() + if str(Roles.tuteur_entreprise) not in user['role'].split('-'): + return {"ERROR": "The user with id " + str(etutor_id) + + " doesn't have the 'etutor' role (" + str(Roles.tuteur_entreprise) + ") !"}, 400 - query = GROUP.update().values(name=name, year=year, class_short=class_short, class_long=class_long, - department=department, resp_id=resp_id, sec_id=sec_id, ressources_dir=res_dir) \ - .where(GROUP.c.id == gid) + if contract_start > contract_end: + return {"ERROR": "The contract start can't be after its end !"}, 400 + + query = LIVRET.update().values(etutor_id=etutor_id, company_name=company_name, + company_address=company_address, contract_type=contract_type, + contract_start=contract_start, contract_end=contract_end, + description=description) \ + .where(LIVRET.c.id == lid) query.execute() - if group["ressources_dir"] != res_dir: - os.rename(group["ressources_dir"], res_dir) - for m in mails: addr = m[0] mail = m[1] send_mail(mail[0], addr, mail[1]) - return {"GID": gid}, 200 + return {"LID": lid}, 200 - def get(self, gid=0, name=""): - if gid > 0: - return {'GROUP': getGroup(gid=gid)}, 200 - elif name != "": - return {'GROUP': getGroup(name=name)}, 200 - - def options(self, gid): - args = request.get_json(cache=False, force=True) - if not checkParams(['pairs'], args): - return {"ERROR": "One or more parameters are missing !"}, 400 - - pairs = args["pairs"] - - group = getGroup(gid=gid) - if group is None: - return {"ERROR": "This group does not exists !"}, 405 - - for p in pairs: - try: - stud = getUser(uid=p[0]) - if stud is None: - return {"ERROR": "The user with id " + str(p[0]) + " does not exists !"}, 400 - elif stud['role'] != "4": - return {"ERROR": "A student must have the 'student' role !"}, 400 - - tutor = getUser(uid=p[1]) - if tutor is None: - return {"ERROR": "The user with id " + str(p[1]) + " does not exists !"}, 400 - elif tutor['role'] == "4": - return {"ERROR": "A student can't be a tutor !"}, 400 - elif "3" not in tutor['role'].split('-'): - role = tutor['role'] + "-3" - query = USER.update().values(role=role).where(USER.c.id == p[1]) - query.execute() - except IndexError: - return {"ERROR": "Pairs are incorrectly formed !"}, 409 - - query = TUTORSHIP.insert().values(group_id=gid, student_id=p[0], ptutor_id=p[1]) - query.execute() - - query = USER.select(USER.c.id == stud["id"]) - rows = query.execute() - res = rows.first() - if res.hash is not None and len(res.hash) > 0: - mail = mailsModels.getMailContent("NEW_STUD_OF_GROUP", {"GROUP": group["name"], - "URL": getParam('OLA_URL') + "registration/" - + res.hash}) - else: - mail = mailsModels.getMailContent("STUD_OF_GROUP", {"GROUP": group["name"], - "URL": getParam('OLA_URL')}) - - send_mail(mail[0], stud["email"], mail[1]) - - return {"RESULT": "Pairs added successfully"}, 200 + @login_required() + def get(self, lid=0, group_id=0, student_id=0): + if lid > 0: + return {'LIVRET': getLivret(lid=lid)}, 200 + elif group_id > 0 and student_id > 0: + return {'LIVRET': getLivret(group_id=group_id, student_id=student_id)}, 200 diff --git a/backend/app/api/LoginAPI.py b/backend/app/api/LoginAPI.py index c426fb3..e99686a 100644 --- a/backend/app/api/LoginAPI.py +++ b/backend/app/api/LoginAPI.py @@ -49,3 +49,14 @@ class LoginAPI(Resource): session['user'] = None return {'AUTH_RESULT': 'OK'}, 200 + +def login_required(roles=[]): + def my_login_required(func): + def wrapper(*args, **kvargs): + current_user = session.get('user', None) + if current_user is None or (len(roles) != 0 and not sum([1 for x in current_user['role'].split("-") if int(x) in roles]) > 0): + return {"ERROR": "UNAUTHORIZED"}, 401 + return func(*args, **kvargs) + return wrapper + return my_login_required + diff --git a/backend/app/api/PdfAPI.py b/backend/app/api/PdfAPI.py index a1e7105..bf831d1 100644 --- a/backend/app/api/PdfAPI.py +++ b/backend/app/api/PdfAPI.py @@ -1,29 +1,29 @@ -import os - -from flask import request from flask_restful import Resource from flask_restful.reqparse import RequestParser +from app.tools.LibPdf import delete_file from model import getParam +from werkzeug.utils import secure_filename from app.model import getGroup -from app.tools.LibPdf import delete_file, upload_file, allowed_file +from app.tools.LibPdf import upload_file, allowed_file +from app.api.LoginAPI import login_required +import os +import request class PdfAPI(Resource): """ Pdf Api Resource """ - + @login_required() def delete(self): parser = RequestParser() parser.add_argument('templateName', required=True, help="Template name is required !") args = parser.parse_args() - if ".." in args: - return {"msg": ".. not allowed in path"}, 400 - - delete_file(os.path.join(getParam('TEMPLATES_DIRECTORY'), args['templateName'])) + delete_file(os.path.join(getParam('TEMPLATES_DIRECTORY'), secure_filename(args['templateName']))) + @login_required() def post(self): """ Upload d'un template diff --git a/backend/app/api/PeriodAPI.py b/backend/app/api/PeriodAPI.py new file mode 100644 index 0000000..975597f --- /dev/null +++ b/backend/app/api/PeriodAPI.py @@ -0,0 +1,116 @@ +import os +from datetime import datetime + +from flask import session +from flask_restful import Resource, request +from sqlalchemy import select, and_ + +from app.api import mailsModels +from app.api.LoginAPI import login_required +from app.model import Roles, getParam, getGroup, getUser, LIVRET, getLivret, TUTORSHIP, PERIOD, getPeriod, \ + TypesPeriode +from app.utils import send_mail, checkParams, get_random_string + + +class PeriodAPI(Resource): + """ + Period Api Resource + """ + + @login_required(roles=[Roles.resp_formation]) + def post(self): + args = request.get_json(cache=False, force=True) + if not checkParams(['group_id', 'period_type', 'start', 'end'], args): + return {"ERROR": "One or more parameters are missing !"}, 400 + + group_id = args['group_id'] + period_type = args['period_type'] + start = datetime.strptime(args['start'], "%d-%m-%Y") + end = datetime.strptime(args['end'], "%d-%m-%Y") + + # On vérifie que le groupe existe + group = getGroup(gid=group_id) + if group is None: + return {"ERROR": "This group with id " + str(group_id) + "does not exists !"}, 405 + + if start > end: + return {"ERROR": "The period's start can't be after its end !"}, 400 + + # On vérifie que l'utilisateur actuel a le droit de modifier ce groupe + user = session.get("user") + if user["id"] != group["resp_id"]: + return {"ERROR": "UNAUTHORIZED"}, 401 + + # On récupère tous les livrets de ce groupe + query = select([LIVRET.c.id, TUTORSHIP.c.student_id]).where( + and_(TUTORSHIP.c.id == LIVRET.c.tutorship_id, TUTORSHIP.c.group_id == group_id)) + res = query.execute() + + # Pour chaque livret du groupe on ajoute la période et on prévient l'étudiant + for row in res: + # On crée un répertoire avec un nom aléatoire + res_dir = group["ressources_dir"] + "/" + str(row.student_id) + "/" + get_random_string() + "/" + while os.path.exists(res_dir): + res_dir = group["ressources_dir"] + "/" + str(row.student_id) + "/" + get_random_string() + "/" + + # Enregistrement des infos en base + query = PERIOD.insert().values(livret_id=row.id, type=period_type, start=start, end=end, + ressources_dir=res_dir) + query.execute() + os.mkdir(res_dir) + + # Envoi d'un mail + mail = mailsModels.getMailContent("NEW_PERIOD", {"GROUPE": group["name"], + "URL": getParam('OLA_URL') + "mon_livret"}) + send_mail(mail[0], getUser(row.student_id)["email"], mail[1]) + + return {"RESULT": "OK"}, 201 + + @login_required(roles=[Roles.etudiant, Roles.tuteur_entreprise]) + def put(self, pid): + args = request.get_json(cache=False, force=True) + if not checkParams(['text'], args): + return {"ERROR": "One or more parameters are missing !"}, 400 + + text = args['text'] + user = session.get("user") + mails = [] + + # On vérifie que la période existe + period = getPeriod(pid) + if period is None: + return {"ERROR": "This period does not exists !"}, 405 + + # On vérifie que l'utilisateur actuel a le droit de modifier ce livret (étudiant ou tuteur) + livret = getLivret(lid=period["livret_id"]) + if user["id"] != livret["etutor_id"]["id"] and user["id"] != livret["tutorship_id"]["student_id"]["id"]: + return {"ERROR": "UNAUTHORIZED"}, 401 + + # Si c'est le commentaire de l'étudiant, on prévient le tuteur + if user["role"] == str(Roles.etudiant): + mail = mailsModels.getMailContent("STUD_COMMENT_ADDED", {"ETUDIANT": user["name"], + "URL": getParam('OLA_URL')}) + mails.append((user["email"], mail)) + query = PERIOD.update().values(student_desc=text).where(PERIOD.c.id == pid) + else: # Sinon on vérifie que c'est une période d'entreprise + if period["type"] == TypesPeriode.universitaire: + return {"ERROR": "A tutor can't modify a university period !"}, 405 + + mail = mailsModels.getMailContent("ETUTOR_COMMENT_ADDED", {"TUTEUR": user["name"], + "URL": getParam('OLA_URL')}) + mails.append((user["email"], mail)) + query = PERIOD.update().values(etutor_desc=text).where(PERIOD.c.id == pid) + + query.execute() + + for m in mails: + addr = m[0] + mail = m[1] + send_mail(mail[0], addr, mail[1]) + + return {"PID": pid}, 200 + + @login_required() + def get(self, pid): + if pid > 0: + return {'PERIOD': getPeriod(pid=pid)}, 200 diff --git a/backend/app/api/UserAPI.py b/backend/app/api/UserAPI.py index f9bfbcb..9b14a41 100644 --- a/backend/app/api/UserAPI.py +++ b/backend/app/api/UserAPI.py @@ -1,8 +1,10 @@ from hashlib import sha256 +from flask import session from flask_restful import Resource, request -from app.model import * +from app.api.LoginAPI import login_required +from app.model import Roles, getUser, hashExists, USER from app.utils import checkParams, get_random_string @@ -11,6 +13,7 @@ class UserAPI(Resource): User Api Resource """ + @login_required(roles=[Roles.resp_formation, Roles.etudiant]) def post(self): args = request.get_json(cache=False, force=True) if not checkParams(['role', 'email', 'name'], args): @@ -52,9 +55,14 @@ class UserAPI(Resource): password = sha256(psw.encode('utf-8')).hexdigest() - if getUser(uid=uid) is None: + user = getUser(uid=uid) + if user is None: return {"ERROR": "This user doesn't exists !"}, 405 + # On n'autorise pas de modifcation anonyme d'un profil s'il est déjà activé (si il a un mdp) + if user["password"] is not None and user["password"] != "" and session.get("user", None) is None: + return {"msg": "UNAUTHORIZED"}, 401 + if getUser(email=email) is not None: return {"ERROR": "A user with this email already exists !"}, 405 @@ -64,9 +72,11 @@ class UserAPI(Resource): return {"UID": uid}, 200 def get(self, uid=0, email="", hashcode=""): - if uid > 0: - return {'USER': getUser(uid=uid)}, 200 - elif email != "": - return {'USER': getUser(email=email)}, 200 - elif hashcode != "": - return {'USER': getUser(hashcode=hashcode)}, 200 + if session.get('user', None) is not None: + if uid > 0: + return {'USER': getUser(uid=uid)}, 200 + elif email != "": + return {'USER': getUser(email=email)}, 200 + + if hashcode != "": + return {'USER': getUser(hashcode=hashcode)}, 200 \ No newline at end of file diff --git a/backend/app/api/UserInfoAPI.py b/backend/app/api/UserInfoAPI.py index c1807e9..eb46881 100644 --- a/backend/app/api/UserInfoAPI.py +++ b/backend/app/api/UserInfoAPI.py @@ -1,7 +1,7 @@ from flask import session from flask_restful import Resource -from app.model import * +from app.model import LIVRET, TUTORSHIP, and_ class UserInfoAPI(Resource): @@ -18,7 +18,6 @@ class UserGroupsAPI(Resource): """ UserGroups Api Resource """ - def get(self): user = session.get("user", None) if user is not None: diff --git a/backend/app/api/mailsModels.py b/backend/app/api/mailsModels.py index e928d94..4fd4cb5 100644 --- a/backend/app/api/mailsModels.py +++ b/backend/app/api/mailsModels.py @@ -11,7 +11,7 @@ _STUD_OF_GROUP = ( _NEW_RESP_OF_GROUP = ("Votre compte OLA a été créé !", "Bonjour,

Votre compte vient d'être créé dans l'Outil du " "Livret de l'Alternant en tant que responsable du groupe #GROUPE. Vous pouvez dès " - "maintenant l'activer, en vous rendant à l'adresse :
" + "maintenant l'activer en vous rendant à l'adresse :
" "#URL

Bonne journée !

") _RESP_OF_GROUP = ( @@ -22,7 +22,7 @@ _RESP_OF_GROUP = ( _NEW_SEC_OF_GROUP = ("Votre compte OLA a été créé !", "Bonjour,

Votre compte vient d'être créé dans l'Outil du " "Livret de l'Alternant en tant que secrétaire du groupe #GROUPE. Vous pouvez dès " - "maintenant l'activer, en vous rendant à l'adresse :
" + "maintenant l'activer en vous rendant à l'adresse :
" "#URL

Bonne journée !

") _SEC_OF_GROUP = ( @@ -31,6 +31,36 @@ _SEC_OF_GROUP = ( "maintenant y accéder en vous rendant à l'adresse :
" "#URL

Bonne journée !

") +_NEW_ETUTOR_ADDED = ("Votre compte OLA a été créé !", "Bonjour,

Votre compte vient d'être créé dans l'Outil du " + "Livret de l'Alternant de l'Université Toulouse Jean-Jaurès en tant que tuteur dans le groupe #GROUPE. Vous pouvez dès " + "maintenant l'activer en vous rendant à l'adresse :
" + "#URL

Bonne journée !

") + +_ETUTOR_ADDED = ( + "Vous avez été déclaré comme tuteur dans OLA !", "Bonjour,

Votre compte vient d'être ajouté dans l'Outil du " + "Livret de l'Alternant de l'Université Toulouse Jean-Jaurès en tant que tuteur dans le groupe #GROUPE. Vous pouvez dès " + "maintenant accéder à votre compte en vous rendant à l'adresse :
" + "#URL

Bonne journée !

") + +_NEW_PERIOD = ( + "Nouvelle période ouverte dans OLA !", "Bonjour,

Une nouvelle période vient d'être crée sur l'Outil du " + "Livret de l'Alternant dans le groupe #GROUPE. Vous pouvez dès " + "maintenant entrer vos commentaires en vous rendant à l'adresse :
" + "#URL

Bonne journée !

") + +_STUD_COMMENT_ADDED = ( + "Livret de l'alternant mis à jour !", "Bonjour,

#ETUDIANT vient de mettre à jour son livret sur l'Outil du " + "Livret de l'Alternant. Vous pouvez dès " + "maintenant entrer à votre tour vos commentaires en vous rendant à l'adresse :
" + "#URL

Bonne journée !

") + +_ETUTOR_COMMENT_ADDED = ( + "Livret de l'alternant mis à jour !", "Bonjour,

#TUTEUR vient de mettre à jour son livret sur l'Outil du " + "Livret de l'Alternant. Vous pouvez visualiser ces modifcations" + " en vous rendant à l'adresse :
" + "#URL

Bonne journée !

") + + def getMailContent(mail_type, args): if mail_type == "NEW_STUD_OF_GROUP": @@ -45,9 +75,21 @@ def getMailContent(mail_type, args): mail = _NEW_SEC_OF_GROUP elif mail_type == "SEC_OF_GROUP": mail = _SEC_OF_GROUP + elif mail_type == "NEW_ETUTOR_ADDED": + mail = _NEW_ETUTOR_ADDED + elif mail_type == "ETUTOR_ADDED": + mail = _ETUTOR_ADDED + elif mail_type == "NEW_PERIOD": + mail = _NEW_PERIOD + elif mail_type == "STUD_COMMENT_ADDED": + mail = _STUD_COMMENT_ADDED + elif mail_type == "ETUTOR_COMMENT_ADDED": + mail = _ETUTOR_COMMENT_ADDED else: - raise Exception("Unknown mail type !") + raise Exception("Unknown mail type : " + str(mail_type)) + obj = mail[0] + content = str(mail[1]) for key, value in args.items(): - mail[1].replace("#" + key, value) - return mail + content = content.replace("#" + key, value) + return (obj, content) diff --git a/backend/app/core.py b/backend/app/core.py index 2b1ac28..0c59ffe 100644 --- a/backend/app/core.py +++ b/backend/app/core.py @@ -45,3 +45,9 @@ def after_login(): # import api resources importlib.import_module("app.urls") + + +@app.teardown_request +def shutdown_session(exception=None): + engine.dispose() + db.session.remove() diff --git a/backend/app/model.py b/backend/app/model.py index 70cc838..495cddc 100644 --- a/backend/app/model.py +++ b/backend/app/model.py @@ -75,13 +75,70 @@ def getGroup(gid=0, name=""): return None -def getTutorshipForStudent(gid, student): - query = TUTORSHIP.select(and_(TUTORSHIP.c.group_id == gid, TUTORSHIP.c.student_id == student)) +def getTutorship(tid=0, gid=0, student=0): + if tid == 0 and gid == 0 and student == 0: + raise Exception("getGroup must be called with at least one argument !") + else: + if gid != 0: + query = TUTORSHIP.select(and_(TUTORSHIP.c.group_id == gid, TUTORSHIP.c.student_id == student)) + rows = query.execute() + res = rows.first() + elif tid != 0: + query = TUTORSHIP.select(TUTORSHIP.c.id == tid) + rows = query.execute() + res = rows.first() + else: + raise Exception("getTutorship must be called with two parameter for group+student search !") + + if res is not None: + return {"id": res.id, "group_id": getGroup(gid=res.group_id), "student_id": getUser(uid=res.student_id), + "ptutor_id": getUser(uid=res.ptutor_id)} + else: + return None + + +def getLivret(lid=0, group_id=0, student_id=0): + res = None + + if lid == 0 and student_id == "": + raise Exception("getLivret must be called with at least one argument !") + else: + if lid != 0: + query = LIVRET.select(LIVRET.c.id == lid) + rows = query.execute() + res = rows.first() + + elif student_id != 0 and group_id != 0: + tutorship = getTutorship(gid=group_id, student=student_id) + if tutorship is None: + return None + query = LIVRET.select(LIVRET.c.tutorship_id == tutorship["id"]) + rows = query.execute() + res = rows.first() + else: + raise Exception("getLivret must be called with two parameter for group+student search !") + + if res is not None: + return {"id": res.id, "tutorship_id": getTutorship(tid=res.tutorship_id), + "etutor_id": getUser(uid=res.etutor_id), "company_name": res.company_name, + "company_address": res.company_address, "contract_type": res.contract_type, + "contract_start": res.contract_start.strftime('%d-%m-%Y'), + "contract_end": res.contract_end.strftime('%d-%m-%Y'), + "ressources_dir": res.ressources_dir, "opened": res.opened, + "expire": res.expire.strftime('%d-%m-%Y')} + else: + return None + + +def getPeriod(pid): + query = PERIOD.select(PERIOD.c.id == pid) rows = query.execute() res = rows.first() + if res is not None: - return {"id": res.id, "group_id": getGroup(gid=res.group_id), "student_id": getUser(uid=res.student_id), - "ptutor_id": getUser(uid=res.ptutor_id)} + return {"id": res.id, "livret_id": res.livret_id, "type": res.type, "start": res.start.strftime('%d-%m-%Y'), + "end": res.end.strftime('%d-%m-%Y'), "student_desc": res.student_desc, "etutor_desc": res.etutor_desc, + "ressources_dir": res.ressources_dir} else: return None @@ -91,3 +148,16 @@ def hashExists(test): rows = query.execute() res = rows.first() return res is not None + + +class Roles: + secretaire = 1 + resp_formation = 2 + tuteur_univ = 3 + etudiant = 4 + tuteur_entreprise = 5 + + +class TypesPeriode: + universitaire = 1 + entreprise = 2 diff --git a/backend/app/tools/LibPdf.py b/backend/app/tools/LibPdf.py index da93aa5..985594a 100644 --- a/backend/app/tools/LibPdf.py +++ b/backend/app/tools/LibPdf.py @@ -55,15 +55,14 @@ def allowed_file(filename): def upload_file(file_to_upload, upload_folder): """ - rep de l'etu avec id - :param file: + televersement d'un fichier + :param file_to_upload: :param upload_folder: :return: """ file_to_upload.save(os.path.join(upload_folder, secure_filename(file_to_upload.filename))) - def delete_file(pdf_path): if os.path.exists(pdf_path): os.remove(pdf_path) diff --git a/backend/app/urls.py b/backend/app/urls.py index 5ccd60b..6c3df66 100644 --- a/backend/app/urls.py +++ b/backend/app/urls.py @@ -1,6 +1,8 @@ +from app.api.GetAllAPI import GetAllAPI from app.api.GroupAPI import GroupAPI from app.api.LivretAPI import LivretAPI from app.api.LoginAPI import LoginAPI +from app.api.PeriodAPI import PeriodAPI from app.api.UserAPI import UserAPI from app.api.UserInfoAPI import UserInfoAPI, UserGroupsAPI from app.api.exampleapi import SomeApi @@ -14,4 +16,7 @@ api.add_resource(UserGroupsAPI, '/api/userGroups') api.add_resource(UserAPI, '/api/user', '/api/user/byuid/', '/api/user/byemail/', '/api/user/byhash/') api.add_resource(GroupAPI, '/api/group', '/api/group/bygid/', '/api/group/byname/') -api.add_resource(LivretAPI, '/api/livret', '/api/livret/byuid/') +api.add_resource(LivretAPI, '/api/livret', '/api/livret/bylid/', + '/api/livret/bytutorship//') +api.add_resource(PeriodAPI, '/api/period', '/api/period/bypid/') +api.add_resource(GetAllAPI, '/api/getAll//') diff --git a/backend/tests/tools/libPdf/UploadPDF/testUploadPdf.py b/backend/tests/tools/libPdf/UploadPDF/testUploadPdf.py index 45e1940..4604a9e 100644 --- a/backend/tests/tools/libPdf/UploadPDF/testUploadPdf.py +++ b/backend/tests/tools/libPdf/UploadPDF/testUploadPdf.py @@ -1,20 +1,25 @@ +import filecmp import os import unittest +from pathlib import Path from werkzeug.datastructures import FileStorage -from app.tools.LibPdf import upload_file +from app.tools.LibPdf import upload_file, allowed_file class TestFusionTestCase(unittest.TestCase): def setUp(self): - self.datadir = os.path.join(os.path.dirname(__file__)) + self.datadir = "upload/page1.pdf" + self.file_name = "page1.pdf" def test_fusion(self): - with open("page1.pdf", 'rb') as fp: + with open(self.file_name, 'rb') as fp: file = FileStorage(fp) upload_file(file, "upload") - # self.assertTrue(Path(self.datadir + "/testFusion.pdf").is_file(), "Pdf fusionne inexistant") - # self.assertTrue(len(get_pdf_from_directory(self.datadir)) > 0, "pdf non trouve") - # os.remove(self.datadir + "/testFusion.pdf") + self.assertTrue(Path(self.datadir).is_file(), "Pdf upload inexistant") + self.assertTrue(filecmp.cmp(self.datadir, self.file_name), "fichiers non identique") + self.assertTrue(allowed_file(self.file_name), "format non conforme") + + os.remove(self.datadir)