2021-09-09 12:49:23 +02:00
|
|
|
"""api.__init__
|
|
|
|
"""
|
2024-07-17 12:03:08 +02:00
|
|
|
|
|
|
|
from functools import wraps
|
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
from flask_json import as_json
|
2021-09-09 12:49:23 +02:00
|
|
|
from flask import Blueprint
|
2024-07-17 12:03:08 +02:00
|
|
|
from flask import current_app, g, request
|
2024-01-21 18:07:56 +01:00
|
|
|
from flask_login import current_user
|
2024-08-06 22:30:30 +02:00
|
|
|
from app import db, log
|
2024-07-17 12:03:08 +02:00
|
|
|
from app.decorators import permission_required
|
2022-08-07 19:56:25 +02:00
|
|
|
from app.scodoc import sco_utils as scu
|
2023-08-26 16:34:56 +02:00
|
|
|
from app.scodoc.sco_exceptions import AccessDenied, ScoException
|
2024-01-21 18:07:56 +01:00
|
|
|
from app.scodoc.sco_permissions import Permission
|
2021-09-09 12:49:23 +02:00
|
|
|
|
2022-07-27 16:03:14 +02:00
|
|
|
api_bp = Blueprint("api", __name__)
|
2022-07-26 09:00:48 +02:00
|
|
|
api_web_bp = Blueprint("apiweb", __name__)
|
2021-09-09 12:49:23 +02:00
|
|
|
|
2023-02-22 02:13:06 +01:00
|
|
|
# HTTP ERROR STATUS
|
|
|
|
API_CLIENT_ERROR = 400 # erreur dans les paramètres fournis par le client
|
|
|
|
|
2021-12-22 00:35:58 +01:00
|
|
|
|
2024-07-17 12:03:08 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
|
2022-08-17 17:24:05 +02:00
|
|
|
@api_bp.errorhandler(ScoException)
|
2023-08-26 16:34:56 +02:00
|
|
|
@api_web_bp.errorhandler(ScoException)
|
2022-08-07 19:56:25 +02:00
|
|
|
@api_bp.errorhandler(404)
|
|
|
|
def api_error_handler(e):
|
|
|
|
"erreurs API => json"
|
2024-08-06 22:30:30 +02:00
|
|
|
log(f"api_error_handler: {e}")
|
2022-08-07 19:56:25 +02:00
|
|
|
return scu.json_error(404, message=str(e))
|
|
|
|
|
|
|
|
|
2023-08-26 16:34:56 +02:00
|
|
|
@api_bp.errorhandler(AccessDenied)
|
|
|
|
@api_web_bp.errorhandler(AccessDenied)
|
|
|
|
def permission_denied_error_handler(exc):
|
|
|
|
"""
|
|
|
|
Renvoie message d'erreur pour l'erreur 403
|
|
|
|
"""
|
|
|
|
return scu.json_error(
|
|
|
|
403, f"operation non autorisee ({exc.args[0] if exc.args else ''})"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-12-22 00:35:58 +01:00
|
|
|
def requested_format(default_format="json", allowed_formats=None):
|
|
|
|
"""Extract required format from query string.
|
|
|
|
* default value is json. A list of allowed formats may be provided
|
|
|
|
(['json'] considered if not provided).
|
|
|
|
* if the required format is not in allowed list, returns None.
|
|
|
|
|
|
|
|
NB: if json in not in allowed_formats, format specification is mandatory.
|
|
|
|
"""
|
|
|
|
format_type = request.args.get("format", default_format)
|
|
|
|
if format_type in (allowed_formats or ["json"]):
|
|
|
|
return format_type
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
2023-05-17 21:16:23 +02:00
|
|
|
@as_json
|
2024-01-21 18:07:56 +01:00
|
|
|
def get_model_api_object(
|
|
|
|
model_cls: db.Model,
|
|
|
|
model_id: int,
|
|
|
|
join_cls: db.Model = None,
|
|
|
|
restrict: bool | None = None,
|
|
|
|
):
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
Retourne une réponse contenant la représentation api de l'objet "Model[model_id]"
|
|
|
|
|
2023-12-22 15:18:20 +01:00
|
|
|
Filtrage du département en fonction d'une classe de jointure (eg: Identite, Formsemestre) -> join_cls
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
exemple d'utilisation : fonction "justificatif()" -> app/api/justificatifs.py
|
2024-01-21 18:07:56 +01:00
|
|
|
|
|
|
|
L'agument restrict est passé to_dict, est signale que l'on veut une version restreinte
|
|
|
|
(sans données personnelles, ou sans informations sur le justificatif d'absence)
|
2023-04-17 15:35:42 +02:00
|
|
|
"""
|
|
|
|
query = model_cls.query.filter_by(id=model_id)
|
|
|
|
if g.scodoc_dept and join_cls is not None:
|
|
|
|
query = query.join(join_cls).filter_by(dept_id=g.scodoc_dept_id)
|
2024-01-05 13:42:55 +01:00
|
|
|
unique: model_cls = query.first()
|
|
|
|
|
|
|
|
if unique is None:
|
|
|
|
return scu.json_error(
|
|
|
|
404,
|
|
|
|
message=f"{model_cls.__name__} inexistant(e)",
|
|
|
|
)
|
2024-01-21 18:07:56 +01:00
|
|
|
if restrict is None:
|
|
|
|
return unique.to_dict(format_api=True)
|
|
|
|
return unique.to_dict(format_api=True, restrict=restrict)
|
2023-04-17 15:35:42 +02:00
|
|
|
|
|
|
|
|
2021-10-28 00:52:23 +02:00
|
|
|
from app.api import tokens
|
2022-08-01 21:42:19 +02:00
|
|
|
from app.api import (
|
2023-04-17 15:35:42 +02:00
|
|
|
assiduites,
|
2022-08-01 21:42:19 +02:00
|
|
|
billets_absences,
|
|
|
|
departements,
|
|
|
|
etudiants,
|
2022-08-05 17:05:24 +02:00
|
|
|
evaluations,
|
2022-08-01 21:42:19 +02:00
|
|
|
formations,
|
|
|
|
formsemestres,
|
2022-08-05 17:05:24 +02:00
|
|
|
jury,
|
2023-04-17 15:35:42 +02:00
|
|
|
justificatifs,
|
2022-08-01 21:42:19 +02:00
|
|
|
logos,
|
2023-08-26 16:34:56 +02:00
|
|
|
moduleimpl,
|
2022-08-01 21:42:19 +02:00
|
|
|
partitions,
|
2023-04-16 05:32:21 +02:00
|
|
|
semset,
|
2022-08-05 17:05:24 +02:00
|
|
|
users,
|
2022-08-01 21:42:19 +02:00
|
|
|
)
|