From 936fe3d716cbc9a3d1ff66ce58208bd1d9ad943f Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 24 Jul 2022 15:51:13 +0200 Subject: [PATCH] =?UTF-8?q?API:=20/etudiants/courants=20avec=20restriction?= =?UTF-8?q?=20aux=20d=C3=A9partements?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/auth.py | 2 ++ app/api/etudiants.py | 69 ++++++++++++++++++++++++++++++++++---------- app/auth/models.py | 14 +++++++++ scodoc.py | 16 ++++++++-- 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/app/api/auth.py b/app/api/auth.py index 1c6738b3d..cae9957db 100644 --- a/app/api/auth.py +++ b/app/api/auth.py @@ -28,6 +28,7 @@ from functools import wraps from flask import g from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth +import flask_login from flask_login import current_user from app import log @@ -61,6 +62,7 @@ def verify_token(token) -> User: """ user = User.check_token(token) if token else None + flask_login.login_user(user) g.current_user = user return user diff --git a/app/api/etudiants.py b/app/api/etudiants.py index c44764398..fc5de0f71 100644 --- a/app/api/etudiants.py +++ b/app/api/etudiants.py @@ -8,7 +8,9 @@ API : accès aux étudiants """ -from flask import jsonify +from flask import g, jsonify +from flask_login import current_user +from sqlalchemy import or_ import app from app.api import bp @@ -27,33 +29,68 @@ from app.scodoc.sco_permissions import Permission @permission_required_api(Permission.ScoView, Permission.APIView) def etudiants_courants(long=False): """ - Liste des étudiants inscrits dans un formsemestre actuellement en cours. + La liste des étudiants des semestres "courants" (tous département) + (date du jour comprise dans la période couverte par le sem.) + dans lesquels l'utilisateur a le rôle APIView (donc tous si le dept du + rôle est None). Exemple de résultat : [ - { - "id": 1, - "nip": 1, - "nom": "MOREL", - "prenom": "JACQUES", - "civilite": "X", - }, - { - "id": 2, - "nip": 2, - "nom": "GILLES", - "prenom": "MAXIME", - "civilite": "X", - }, + { + "id": 1234, + "nip": "12345678", + "ine": null, + "nom": "JOHN", + "nom_usuel": None, + "prenom": "DEUF", + "civilite": "M", + } ... ] + + En format "long": + { + "boursier": True, + "civilite": "F", + "code_ine": "AP987654", + "code_nip": "1234567", + "codepostaldomicile": "92800", + "date_naissance": "21/06/2000", + "dept_acronym": "CJ", + "dept_id": 1, + "dept_naissance": "092", + "description": "infos portail", + "domicile": "Plaza Condell", + "email": "jeanne.dupont@xxx.fr", + "emailperso": "", + "etudid": 4853, + "id": 4863, + "lieu_naissance": "SEVRES", + "nationalite": "", + "nom": "DUPONT", + "nomprenom": "Mme Jeanne Dupont", + "paysdomicile": "FRANCE", + "prenom": "JEANNE", + "telephone": "0102030405", + "telephonemobile": "", + "typeadresse": "domicile", + "villedomicile": "VALPARAISO", + } """ + allowed_depts = current_user.get_depts_with_permission( + Permission.APIView | Permission.ScoView + ) etuds = Identite.query.filter( Identite.id == FormSemestreInscription.etudid, FormSemestreInscription.formsemestre_id == FormSemestre.id, FormSemestre.date_debut <= app.db.func.now(), FormSemestre.date_fin >= app.db.func.now(), ) + if not None in allowed_depts: + # restreint aux départements autorisés: + etuds = etuds.join(Departement).filter( + or_(Departement.acronym == acronym for acronym in allowed_depts) + ) if long: data = [etud.to_dict_bul(include_urls=False) for etud in etuds] else: diff --git a/app/auth/models.py b/app/auth/models.py index 3750ea3f8..c5b06444c 100644 --- a/app/auth/models.py +++ b/app/auth/models.py @@ -315,6 +315,20 @@ class User(UserMixin, db.Model): if r is not None ) + def get_depts_with_permission(self, permission: int) -> list[str]: + """Liste des acronymes de département dans lesquels cet utilisateur + possède la permission indiquée. + L'"acronyme" None signifie "tous les départements". + Si plusieurs permissions (plusieurs bits) sont indiquées, c'est un "ou": + les départements dans lesquels l'utilisateur a l'une des permissions. + """ + return [ + user_role.dept + for user_role in UserRole.query.filter_by(user=self) + .join(Role) + .filter(Role.permissions.op("&")(permission) != 0) + ] + def is_administrator(self): "True if i'm an active SuperAdmin" return self.active and self.has_permission(Permission.ScoSuperAdmin, dept=None) diff --git a/scodoc.py b/scodoc.py index 66c0a175a..253e62aa8 100755 --- a/scodoc.py +++ b/scodoc.py @@ -276,6 +276,7 @@ def edit_role(rolename, addpermissionname=None, removepermissionname=None): # e if perm_to_add or perm_to_remove: db.session.add(role) db.session.commit() + print(role) @app.cli.command() @@ -301,16 +302,27 @@ def user_role(username, dept_acronym=None, add_role_name=None, remove_role_name= if not user: sys.stderr.write(f"user_role: user {username} does not exists\n") return 1 + # Sans argument, affiche les rôles de l'utilisateur + if dept_acronym is None and add_role_name is None and remove_role_name is None: + print(f"Roles for user {user.user_name}") + for user_role in sorted( + user.user_roles, key=lambda ur: (ur.dept or "", ur.role.name) + ): + print(f"""{user_role.dept or "tous"}:\t{user_role.role.name}""") + if dept_acronym: dept = models.Departement.query.filter_by(acronym=dept_acronym).first() if dept is None: - sys.stderr.write(f"Erreur: le departement {dept} n'existe pas !\n") + sys.stderr.write(f"Erreur: le departement {dept_acronym} n'existe pas !\n") return 2 if add_role_name: role = Role.query.filter_by(name=add_role_name).first() if role is None: - sys.stderr.write(f"user_role: role {add_role_name} does not exists\n") + sys.stderr.write( + f"""user_role: role {add_role_name} does not exists + (use list-roles to display existing roles)\n""" + ) return 2 user.add_role(role, dept_acronym) if remove_role_name: