From 335bd04803cb1890c966f69ca22e424b3ea6d75e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20ARNAUDEAU?= Date: Mon, 8 May 2017 19:51:28 +0200 Subject: [PATCH] =?UTF-8?q?TG-40=20:=20PeriodAPI=20+=20S=C3=A9curisation?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/app/api/GetAllAPI.py | 31 +++++++++ backend/app/api/LivretAPI.py | 19 ++++-- backend/app/api/PeriodAPI.py | 116 +++++++++++++++++++++++++++++++++ backend/app/api/mailsModels.py | 27 +++++++- backend/app/core.py | 6 ++ backend/app/model.py | 18 +++++ backend/app/urls.py | 4 ++ 7 files changed, 215 insertions(+), 6 deletions(-) create mode 100644 backend/app/api/GetAllAPI.py create mode 100644 backend/app/api/PeriodAPI.py 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/LivretAPI.py b/backend/app/api/LivretAPI.py index 02f6f9d..4ce7d3a 100644 --- a/backend/app/api/LivretAPI.py +++ b/backend/app/api/LivretAPI.py @@ -48,11 +48,15 @@ class LivretAPI(Resource): if livret is not None: return {"LID": livret["id"]}, 200 - user = getUser(uid=etutor_id) - if user is None: + # 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: @@ -63,8 +67,8 @@ class LivretAPI(Resource): mail = mailsModels.getMailContent("ETUTOR_ADDED", {"GROUPE": group["name"], "URL": getParam('OLA_URL')}) - mails.append((user["email"], mail)) - if str(Roles.tuteur_entreprise) not in user['role'].split('-'): + 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 @@ -108,6 +112,11 @@ class LivretAPI(Resource): if livret is None: return {"ERROR": "This livret does not 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=etutor_id) if user is None: return {"ERROR": "The user with id " + str(etutor_id) + " does not exists !"}, 400 diff --git a/backend/app/api/PeriodAPI.py b/backend/app/api/PeriodAPI.py new file mode 100644 index 0000000..1cd752d --- /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 !"} + + 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/mailsModels.py b/backend/app/api/mailsModels.py index c64d0dd..4fd4cb5 100644 --- a/backend/app/api/mailsModels.py +++ b/backend/app/api/mailsModels.py @@ -42,6 +42,25 @@ _ETUTOR_ADDED = ( "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": @@ -60,8 +79,14 @@ def getMailContent(mail_type, args): 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]) 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 5861f3b..495cddc 100644 --- a/backend/app/model.py +++ b/backend/app/model.py @@ -130,6 +130,19 @@ def getLivret(lid=0, group_id=0, student_id=0): 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, "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 + + def hashExists(test): query = USER.select(USER.c.hash == test) rows = query.execute() @@ -143,3 +156,8 @@ class Roles: tuteur_univ = 3 etudiant = 4 tuteur_entreprise = 5 + + +class TypesPeriode: + universitaire = 1 + entreprise = 2 diff --git a/backend/app/urls.py b/backend/app/urls.py index 2a0027d..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 @@ -16,3 +18,5 @@ api.add_resource(UserAPI, '/api/user', '/api/user/byuid/', '/api/user/b api.add_resource(GroupAPI, '/api/group', '/api/group/bygid/', '/api/group/byname/') 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//')