From 7623ccef2bb60aae511ec9373a07dfe28b21fca4 Mon Sep 17 00:00:00 2001
From: Emmanuel Viennet <emmanuel.viennet@gmail.com>
Date: Wed, 17 Jul 2024 12:03:08 +0200
Subject: [PATCH] =?UTF-8?q?API:=20d=C3=A9corateur=20api=5Fpermission=5Freq?=
 =?UTF-8?q?uired=20pour=20la=20documentation?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 app/api/__init__.py      | 28 +++++++++++++++++++++++++++-
 app/api/etudiants.py     |  3 ++-
 app/api/evaluations.py   |  3 ++-
 app/api/formations.py    |  3 ++-
 app/api/formsemestres.py |  3 ++-
 app/api/jury.py          |  3 ++-
 app/api/justificatifs.py |  3 ++-
 app/api/logos.py         |  6 ++++--
 app/api/moduleimpl.py    |  3 ++-
 app/api/partitions.py    |  3 ++-
 app/api/users.py         |  7 +++----
 app/decorators.py        |  3 +++
 12 files changed, 53 insertions(+), 15 deletions(-)

diff --git a/app/api/__init__.py b/app/api/__init__.py
index fb994bfdd..8a2054249 100644
--- a/app/api/__init__.py
+++ b/app/api/__init__.py
@@ -1,10 +1,14 @@
 """api.__init__
 """
+
+from functools import wraps
+
 from flask_json import as_json
 from flask import Blueprint
-from flask import request, g
+from flask import current_app, g, request
 from flask_login import current_user
 from app import db
+from app.decorators import permission_required
 from app.scodoc import sco_utils as scu
 from app.scodoc.sco_exceptions import AccessDenied, ScoException
 from app.scodoc.sco_permissions import Permission
@@ -16,6 +20,28 @@ api_web_bp = Blueprint("apiweb", __name__)
 API_CLIENT_ERROR = 400  # erreur dans les paramètres fournis par le client
 
 
+def api_permission_required(permission):
+    """Ce décorateur fait la même chose que @permission_required
+    mais enregistre dans l'attribut .scodoc_permission
+    de la fonction la valeur de la permission.
+    Cette valeur n'est utilisée que pour la génération automatique de la documentation.
+    """
+
+    def decorator(f):
+        f.scodoc_permission = permission
+
+        @wraps(f)
+        def decorated_function(*args, **kwargs):
+            scodoc_dept = getattr(g, "scodoc_dept", None)
+            if not current_user.has_permission(permission, scodoc_dept):
+                return current_app.login_manager.unauthorized()
+            return f(*args, **kwargs)
+
+        return decorated_function
+
+    return decorator
+
+
 @api_bp.errorhandler(ScoException)
 @api_web_bp.errorhandler(ScoException)
 @api_bp.errorhandler(404)
diff --git a/app/api/etudiants.py b/app/api/etudiants.py
index 5ec9f04a5..72f15b6f2 100755
--- a/app/api/etudiants.py
+++ b/app/api/etudiants.py
@@ -21,8 +21,9 @@ import app
 from app import db, log
 from app.api import api_bp as bp, api_web_bp
 from app.api import tools
+from app.api import api_permission_required as permission_required
 from app.but import bulletin_but_court
-from app.decorators import scodoc, permission_required
+from app.decorators import scodoc
 from app.models import (
     Admission,
     Departement,
diff --git a/app/api/evaluations.py b/app/api/evaluations.py
index 510ad988d..3eafaffb9 100644
--- a/app/api/evaluations.py
+++ b/app/api/evaluations.py
@@ -14,7 +14,8 @@ from flask_login import current_user, login_required
 import app
 from app import log, db
 from app.api import api_bp as bp, api_web_bp
-from app.decorators import scodoc, permission_required
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.models import Evaluation, ModuleImpl, FormSemestre
 from app.scodoc import sco_evaluation_db, sco_saisie_notes
 from app.scodoc.sco_exceptions import AccessDenied, ScoValueError
diff --git a/app/api/formations.py b/app/api/formations.py
index bce8861bd..8f5601f4b 100644
--- a/app/api/formations.py
+++ b/app/api/formations.py
@@ -15,9 +15,10 @@ from flask_login import login_required
 import app
 from app import db, log
 from app.api import api_bp as bp, api_web_bp
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.models import APO_CODE_STR_LEN
 from app.scodoc.sco_utils import json_error
-from app.decorators import scodoc, permission_required
 from app.models import (
     ApcNiveau,
     ApcParcours,
diff --git a/app/api/formsemestres.py b/app/api/formsemestres.py
index 6239c1278..e3d8d24c5 100644
--- a/app/api/formsemestres.py
+++ b/app/api/formsemestres.py
@@ -16,7 +16,8 @@ import sqlalchemy as sa
 import app
 from app import db, log
 from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
-from app.decorators import scodoc, permission_required
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.scodoc.sco_utils import json_error
 from app.comp import res_sem
 from app.comp.moy_mod import ModuleImplResults
diff --git a/app/api/jury.py b/app/api/jury.py
index 4fce0bfa0..ef00cb84d 100644
--- a/app/api/jury.py
+++ b/app/api/jury.py
@@ -17,7 +17,8 @@ from flask_login import current_user, login_required
 import app
 from app import db, log
 from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR, tools
-from app.decorators import scodoc, permission_required
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.scodoc.sco_exceptions import ScoException
 from app.but import jury_but_results
 from app.models import (
diff --git a/app/api/justificatifs.py b/app/api/justificatifs.py
index 79c05d8ef..eacd6778c 100644
--- a/app/api/justificatifs.py
+++ b/app/api/justificatifs.py
@@ -19,7 +19,8 @@ from app import db, set_sco_dept
 from app.api import api_bp as bp
 from app.api import api_web_bp
 from app.api import get_model_api_object, tools
-from app.decorators import permission_required, scodoc
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.models import Identite, Justificatif, Departement, FormSemestre, Scolog
 from app.models.assiduites import (
     get_formsemestre_from_data,
diff --git a/app/api/logos.py b/app/api/logos.py
index 08b59e370..319e258cd 100644
--- a/app/api/logos.py
+++ b/app/api/logos.py
@@ -34,11 +34,13 @@ from flask import Response, send_file
 from flask_json import as_json
 
 from app.api import api_bp as bp
-from app.scodoc.sco_utils import json_error
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.models import Departement
 from app.scodoc.sco_logos import list_logos, find_logo
-from app.decorators import scodoc, permission_required
 from app.scodoc.sco_permissions import Permission
+from app.scodoc.sco_utils import json_error
+
 
 # Note: l'API logos n'est accessible qu'en mode global (avec jeton, sans dept)
 
diff --git a/app/api/moduleimpl.py b/app/api/moduleimpl.py
index 4b5db1b0f..e7999f71a 100644
--- a/app/api/moduleimpl.py
+++ b/app/api/moduleimpl.py
@@ -13,7 +13,8 @@ from flask_login import login_required
 
 import app
 from app.api import api_bp as bp, api_web_bp
-from app.decorators import scodoc, permission_required
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.models import ModuleImpl
 from app.scodoc import sco_liste_notes
 from app.scodoc.sco_permissions import Permission
diff --git a/app/api/partitions.py b/app/api/partitions.py
index 54c30355f..bd45f9103 100644
--- a/app/api/partitions.py
+++ b/app/api/partitions.py
@@ -18,7 +18,8 @@ from sqlalchemy.exc import IntegrityError
 import app
 from app import db, log
 from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
-from app.decorators import scodoc, permission_required
+from app.api import api_permission_required as permission_required
+from app.decorators import scodoc
 from app.scodoc.sco_utils import json_error
 from app.models import FormSemestre, FormSemestreInscription, Identite
 from app.models import GroupDescr, Partition, Scolog
diff --git a/app/api/users.py b/app/api/users.py
index f1a600935..37295a63d 100644
--- a/app/api/users.py
+++ b/app/api/users.py
@@ -14,15 +14,14 @@ from flask_login import current_user, login_required
 
 from app import db, log
 from app.api import api_bp as bp, api_web_bp, API_CLIENT_ERROR
+from app.api import api_permission_required as permission_required
 from app.auth.models import User, Role, UserRole
 from app.auth.models import is_valid_password
-from app.decorators import scodoc, permission_required
-from app.models import Departement, ScoDocSiteConfig
-from app.scodoc import sco_edt_cal
+from app.decorators import scodoc
+from app.models import Departement
 from app.scodoc.sco_exceptions import ScoValueError
 from app.scodoc.sco_permissions import Permission
 from app.scodoc.sco_utils import json_error
-from app.scodoc import sco_utils as scu
 
 
 @bp.route("/user/<int:uid>")
diff --git a/app/decorators.py b/app/decorators.py
index 85b17a33a..f84ca85a6 100644
--- a/app/decorators.py
+++ b/app/decorators.py
@@ -84,6 +84,9 @@ def scodoc(func):
 
 
 def permission_required(permission):
+    """Vérifie les permissions"""
+
+    # Attention: l'API utilise api_permission_required
     def decorator(f):
         @wraps(f)
         def decorated_function(*args, **kwargs):
-- 
GitLab