1
0
forked from ScoDoc/ScoDoc

API: unifie traitement errors, messages JSON.

This commit is contained in:
Emmanuel Viennet 2022-08-07 19:56:25 +02:00
parent a053afeba6
commit f7a2c1e8e7
24 changed files with 159 additions and 185 deletions

View File

@ -3,11 +3,18 @@
from flask import Blueprint from flask import Blueprint
from flask import request from flask import request
from app.scodoc import sco_utils as scu
api_bp = Blueprint("api", __name__) api_bp = Blueprint("api", __name__)
api_web_bp = Blueprint("apiweb", __name__) api_web_bp = Blueprint("apiweb", __name__)
@api_bp.errorhandler(404)
def api_error_handler(e):
"erreurs API => json"
return scu.json_error(404, message=str(e))
def requested_format(default_format="json", allowed_formats=None): def requested_format(default_format="json", allowed_formats=None):
"""Extract required format from query string. """Extract required format from query string.
* default value is json. A list of allowed formats may be provided * default value is json. A list of allowed formats may be provided

View File

@ -9,7 +9,7 @@
from flask import jsonify from flask import jsonify
from app.api import api_bp as bp from app.api import api_bp as bp
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.models import Identite from app.models import Identite
@ -53,7 +53,7 @@ def absences(etudid: int = None):
""" """
etud = Identite.query.get(etudid) etud = Identite.query.get(etudid)
if etud is None: if etud is None:
return error_response(404, message="etudiant inexistant") return json_error(404, message="etudiant inexistant")
# Absences de l'étudiant # Absences de l'étudiant
ndb.open_db_connection() ndb.open_db_connection()
abs_list = sco_abs.list_abs_date(etud.id) abs_list = sco_abs.list_abs_date(etud.id)
@ -97,7 +97,7 @@ def absences_just(etudid: int = None):
""" """
etud = Identite.query.get(etudid) etud = Identite.query.get(etudid)
if etud is None: if etud is None:
return error_response(404, message="etudiant inexistant") return json_error(404, message="etudiant inexistant")
# Absences justifiées de l'étudiant # Absences justifiées de l'étudiant
abs_just = [ abs_just = [

View File

@ -15,7 +15,7 @@ import app
from app import db from app import db
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.models import BilletAbsence from app.models import BilletAbsence
from app.models.etudiants import Identite from app.models.etudiants import Identite
from app.scodoc import sco_abs_billets from app.scodoc import sco_abs_billets
@ -47,7 +47,7 @@ def billets_absence_create():
description = data.get("description", "") description = data.get("description", "")
justified = data.get("justified", False) justified = data.get("justified", False)
if None in (etudid, abs_begin, abs_end): if None in (etudid, abs_begin, abs_end):
return error_response( return json_error(
404, message="Paramètre manquant: etudid, abs_bein, abs_end requis" 404, message="Paramètre manquant: etudid, abs_bein, abs_end requis"
) )
query = Identite.query.filter_by(etudid=etudid) query = Identite.query.filter_by(etudid=etudid)

View File

@ -17,7 +17,7 @@ from flask_login import login_required
import app import app
from app import db, log from app import db, log
from app.api import api_bp as bp from app.api import api_bp as bp
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.models import Departement, FormSemestre from app.models import Departement, FormSemestre
from app.models import departements from app.models import departements
@ -103,12 +103,12 @@ def departement_create():
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
acronym = str(data.get("acronym", "")) acronym = str(data.get("acronym", ""))
if not acronym: if not acronym:
return error_response(404, "missing acronym") return json_error(404, "missing acronym")
visible = bool(data.get("visible", True)) visible = bool(data.get("visible", True))
try: try:
dept = departements.create_dept(acronym, visible=visible) dept = departements.create_dept(acronym, visible=visible)
except ScoValueError as exc: except ScoValueError as exc:
return error_response(404, exc.args[0] if exc.args else "") return json_error(404, exc.args[0] if exc.args else "")
return jsonify(dept.to_dict()) return jsonify(dept.to_dict())
@ -128,7 +128,7 @@ def departement_edit(acronym):
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
visible = bool(data.get("visible", None)) visible = bool(data.get("visible", None))
if visible is None: if visible is None:
return error_response(404, "missing argument: visible") return json_error(404, "missing argument: visible")
visible = bool(visible) visible = bool(visible)
dept.visible = visible dept.visible = visible
db.session.add(dept) db.session.add(dept)

View File

@ -1,41 +0,0 @@
# Authentication code borrowed from Miguel Grinberg's Mega Tutorial
# (see https://github.com/miguelgrinberg/microblog)
# Under The MIT License (MIT)
# Copyright (c) 2017 Miguel Grinberg
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
from flask import jsonify
from werkzeug.http import HTTP_STATUS_CODES
def error_response(status_code, message=None):
"""Réponse sur erreur"""
payload = {"error": HTTP_STATUS_CODES.get(status_code, "Unknown error")}
if message:
payload["message"] = message
response = jsonify(payload)
response.status_code = status_code
return response
def bad_request(message):
"400 Bad Request response"
return error_response(400, message)

View File

@ -15,7 +15,7 @@ from sqlalchemy import desc, or_
import app import app
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.api import tools from app.api import tools
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.models import ( from app.models import (
@ -116,7 +116,7 @@ def etudiant(etudid: int = None, nip: str = None, ine: str = None):
etud = tools.get_etud(etudid, nip, ine) etud = tools.get_etud(etudid, nip, ine)
if etud is None: if etud is None:
return error_response( return json_error(
404, 404,
message="étudiant inconnu", message="étudiant inconnu",
) )
@ -148,7 +148,7 @@ def etudiants(etudid: int = None, nip: str = None, ine: str = None):
elif ine is not None: elif ine is not None:
query = Identite.query.filter_by(code_ine=ine) query = Identite.query.filter_by(code_ine=ine)
else: else:
return error_response( return json_error(
404, 404,
message="parametre manquant", message="parametre manquant",
) )
@ -185,12 +185,12 @@ def etudiant_formsemestres(etudid: int = None, nip: int = None, ine: int = None)
elif ine is not None: elif ine is not None:
q_etud = Identite.query.filter_by(code_ine=ine) q_etud = Identite.query.filter_by(code_ine=ine)
else: else:
return error_response(404, message="parametre manquant") return json_error(404, message="parametre manquant")
if g.scodoc_dept is not None: if g.scodoc_dept is not None:
q_etud = q_etud.filter_by(dept_id=g.scodoc_dept_id) q_etud = q_etud.filter_by(dept_id=g.scodoc_dept_id)
etud = q_etud.join(Admission).order_by(desc(Admission.annee)).first() etud = q_etud.join(Admission).order_by(desc(Admission.annee)).first()
if etud is None: if etud is None:
return error_response(404, message="etudiant inexistant") return json_error(404, message="etudiant inexistant")
query = FormSemestre.query.filter( query = FormSemestre.query.filter(
FormSemestreInscription.etudid == etud.id, FormSemestreInscription.etudid == etud.id,
FormSemestreInscription.formsemestre_id == FormSemestre.id, FormSemestreInscription.formsemestre_id == FormSemestre.id,
@ -328,7 +328,7 @@ def etudiant_bulletin_semestre(
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404() formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404() dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404()
if g.scodoc_dept and dept != g.scodoc_dept: if g.scodoc_dept and dept != g.scodoc_dept:
return error_response(404, "formsemestre non trouve") return json_error(404, "formsemestre non trouve")
if etudid is not None: if etudid is not None:
query = Identite.query.filter_by(id=etudid) query = Identite.query.filter_by(id=etudid)
elif nip is not None: elif nip is not None:
@ -336,11 +336,11 @@ def etudiant_bulletin_semestre(
elif ine is not None: elif ine is not None:
query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id) query = Identite.query.filter_by(code_ine=ine, dept_id=dept.id)
else: else:
return error_response(404, message="parametre manquant") return json_error(404, message="parametre manquant")
etud = query.first() etud = query.first()
if etud is None: if etud is None:
return error_response(404, message="etudiant inexistant") return json_error(404, message="etudiant inexistant")
app.set_sco_dept(dept.acronym) app.set_sco_dept(dept.acronym)
@ -400,7 +400,7 @@ def etudiant_groups(formsemestre_id: int, etudid: int = None):
query = query.filter_by(dept_id=g.scodoc_dept_id) query = query.filter_by(dept_id=g.scodoc_dept_id)
formsemestre = query.first() formsemestre = query.first()
if formsemestre is None: if formsemestre is None:
return error_response( return json_error(
404, 404,
message="formsemestre inconnu", message="formsemestre inconnu",
) )

View File

@ -15,7 +15,7 @@ import app
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.models import Evaluation, ModuleImpl, FormSemestre from app.models import Evaluation, ModuleImpl, FormSemestre
from app.scodoc import sco_evaluation_db from app.scodoc import sco_evaluation_db
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission

View File

@ -13,7 +13,7 @@ from flask_login import login_required
import app import app
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.models.formations import Formation from app.models.formations import Formation
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
@ -210,7 +210,7 @@ def formation_export_by_formation_id(formation_id: int, export_ids=False):
try: try:
data = sco_formations.formation_export(formation_id, export_ids) data = sco_formations.formation_export(formation_id, export_ids)
except ValueError: except ValueError:
return error_response(500, message="Erreur inconnue") return json_error(500, message="Erreur inconnue")
return jsonify(data) return jsonify(data)

View File

@ -13,7 +13,7 @@ from flask_login import login_required
import app import app
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.comp import res_sem from app.comp import res_sem
from app.comp.moy_mod import ModuleImplResults from app.comp.moy_mod import ModuleImplResults
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
@ -107,7 +107,7 @@ def formsemestres_query():
try: try:
annee_scolaire_int = int(annee_scolaire) annee_scolaire_int = int(annee_scolaire)
except ValueError: except ValueError:
return error_response(404, "invalid annee_scolaire: not int") return json_error(404, "invalid annee_scolaire: not int")
debut_annee = scu.date_debut_anne_scolaire(annee_scolaire_int) debut_annee = scu.date_debut_anne_scolaire(annee_scolaire_int)
fin_annee = scu.date_fin_anne_scolaire(annee_scolaire_int) fin_annee = scu.date_fin_anne_scolaire(annee_scolaire_int)
formsemestres = formsemestres.filter( formsemestres = formsemestres.filter(
@ -119,7 +119,7 @@ def formsemestres_query():
try: try:
dept_id = int(dept_id) dept_id = int(dept_id)
except ValueError: except ValueError:
return error_response(404, "invalid dept_id: not int") return json_error(404, "invalid dept_id: not int")
formsemestres = formsemestres.filter_by(dept_id=dept_id) formsemestres = formsemestres.filter_by(dept_id=dept_id)
if etape_apo is not None: if etape_apo is not None:
formsemestres = formsemestres.join(FormSemestreEtape).filter( formsemestres = formsemestres.join(FormSemestreEtape).filter(
@ -417,7 +417,7 @@ def formsemestre_resultat(formsemestre_id: int):
""" """
format_spec = request.args.get("format", None) format_spec = request.args.get("format", None)
if format_spec is not None and format_spec != "raw": if format_spec is not None and format_spec != "raw":
return error_response(404, "invalid format specification") return json_error(404, "invalid format specification")
convert_values = format_spec != "raw" convert_values = format_spec != "raw"
query = FormSemestre.query.filter_by(id=formsemestre_id) query = FormSemestre.query.filter_by(id=formsemestre_id)

View File

@ -15,7 +15,7 @@ import app
from app import db, log from app import db, log
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.but import jury_but_recap from app.but import jury_but_recap
from app.models import FormSemestre, FormSemestreInscription, Identite from app.models import FormSemestre, FormSemestreInscription, Identite
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission

View File

@ -35,7 +35,7 @@ from flask_login import login_required
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.api import requested_format from app.api import requested_format
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.models import Departement from app.models import Departement
from app.scodoc.sco_logos import list_logos, find_logo from app.scodoc.sco_logos import list_logos, find_logo
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
@ -49,10 +49,10 @@ from app.scodoc.sco_permissions import Permission
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def api_get_glob_logos(): def api_get_glob_logos():
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None): if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
return error_response(401, message="accès interdit") return json_error(403, message="accès interdit")
required_format = requested_format() # json only required_format = requested_format() # json only
if required_format is None: if required_format is None:
return error_response(400, "Illegal format") return json_error(400, "Illegal format")
logos = list_logos()[None] logos = list_logos()[None]
return jsonify(list(logos.keys())) return jsonify(list(logos.keys()))
@ -62,10 +62,10 @@ def api_get_glob_logos():
@permission_required(Permission.ScoView) @permission_required(Permission.ScoView)
def api_get_glob_logo(logoname): def api_get_glob_logo(logoname):
if not g.current_user.has_permission(Permission.ScoSuperAdmin, None): if not g.current_user.has_permission(Permission.ScoSuperAdmin, None):
return error_response(401, message="accès interdit") return json_error(403, message="accès interdit")
logo = find_logo(logoname=logoname) logo = find_logo(logoname=logoname)
if logo is None: if logo is None:
return error_response(404, message="logo not found") return json_error(404, message="logo not found")
logo.select() logo.select()
return send_file( return send_file(
logo.filepath, logo.filepath,
@ -80,7 +80,7 @@ def api_get_glob_logo(logoname):
def api_get_local_logos(departement): def api_get_local_logos(departement):
dept_id = Departement.from_acronym(departement).id dept_id = Departement.from_acronym(departement).id
if not g.current_user.has_permission(Permission.ScoChangePreferences, departement): if not g.current_user.has_permission(Permission.ScoChangePreferences, departement):
return error_response(401, message="accès interdit") return json_error(403, message="accès interdit")
logos = list_logos().get(dept_id, dict()) logos = list_logos().get(dept_id, dict())
return jsonify(list(logos.keys())) return jsonify(list(logos.keys()))
@ -92,10 +92,10 @@ def api_get_local_logo(departement, logoname):
# format = requested_format("jpg", ['png', 'jpg']) XXX ? # format = requested_format("jpg", ['png', 'jpg']) XXX ?
dept_id = Departement.from_acronym(departement).id dept_id = Departement.from_acronym(departement).id
if not g.current_user.has_permission(Permission.ScoChangePreferences, departement): if not g.current_user.has_permission(Permission.ScoChangePreferences, departement):
return error_response(401, message="accès interdit") return json_error(403, message="accès interdit")
logo = find_logo(logoname=logoname, dept_id=dept_id) logo = find_logo(logoname=logoname, dept_id=dept_id)
if logo is None: if logo is None:
return error_response(404, message="logo not found") return json_error(404, message="logo not found")
logo.select() logo.select()
return send_file( return send_file(
logo.filepath, logo.filepath,

View File

@ -14,7 +14,7 @@ import app
from app import db, log from app import db, log
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.models import FormSemestre, FormSemestreInscription, Identite from app.models import FormSemestre, FormSemestreInscription, Identite
from app.models import GroupDescr, Partition from app.models import GroupDescr, Partition
from app.models.groups import group_membership from app.models.groups import group_membership
@ -137,7 +137,7 @@ def etud_in_group_query(group_id: int):
"""Etudiants du groupe, filtrés par état""" """Etudiants du groupe, filtrés par état"""
etat = request.args.get("etat") etat = request.args.get("etat")
if etat not in {scu.INSCRIT, scu.DEMISSION, scu.DEF}: if etat not in {scu.INSCRIT, scu.DEMISSION, scu.DEF}:
return error_response(404, "etat: valeur invalide") return json_error(404, "etat: valeur invalide")
query = GroupDescr.query.filter_by(id=group_id) query = GroupDescr.query.filter_by(id=group_id)
if g.scodoc_dept: if g.scodoc_dept:
query = ( query = (
@ -169,7 +169,7 @@ def set_etud_group(etudid: int, group_id: int):
) )
group = query.first_or_404() group = query.first_or_404()
if etud.id not in {e.id for e in group.partition.formsemestre.etuds}: if etud.id not in {e.id for e in group.partition.formsemestre.etuds}:
return error_response(404, "etud non inscrit au formsemestre du groupe") return json_error(404, "etud non inscrit au formsemestre du groupe")
groups = ( groups = (
GroupDescr.query.filter_by(partition_id=group.partition.id) GroupDescr.query.filter_by(partition_id=group.partition.id)
.join(group_membership) .join(group_membership)
@ -261,13 +261,13 @@ def group_create(partition_id: int):
query = query.join(FormSemestre).filter_by(dept_id=g.scodoc_dept_id) query = query.join(FormSemestre).filter_by(dept_id=g.scodoc_dept_id)
partition: Partition = query.first_or_404() partition: Partition = query.first_or_404()
if not partition.groups_editable: if not partition.groups_editable:
return error_response(404, "partition non editable") return json_error(404, "partition non editable")
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
group_name = data.get("group_name") group_name = data.get("group_name")
if group_name is None: if group_name is None:
return error_response(404, "missing group name or invalid data format") return json_error(404, "missing group name or invalid data format")
if not GroupDescr.check_name(partition, group_name): if not GroupDescr.check_name(partition, group_name):
return error_response(404, "invalid group_name") return json_error(404, "invalid group_name")
group_name = group_name.strip() group_name = group_name.strip()
group = GroupDescr(group_name=group_name, partition_id=partition_id) group = GroupDescr(group_name=group_name, partition_id=partition_id)
@ -293,7 +293,7 @@ def group_delete(group_id: int):
) )
group: GroupDescr = query.first_or_404() group: GroupDescr = query.first_or_404()
if not group.partition.groups_editable: if not group.partition.groups_editable:
return error_response(404, "partition non editable") return json_error(404, "partition non editable")
formsemestre_id = group.partition.formsemestre_id formsemestre_id = group.partition.formsemestre_id
log(f"deleting {group}") log(f"deleting {group}")
db.session.delete(group) db.session.delete(group)
@ -317,12 +317,12 @@ def group_edit(group_id: int):
) )
group: GroupDescr = query.first_or_404() group: GroupDescr = query.first_or_404()
if not group.partition.groups_editable: if not group.partition.groups_editable:
return error_response(404, "partition non editable") return json_error(404, "partition non editable")
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
group_name = data.get("group_name") group_name = data.get("group_name")
if group_name is not None: if group_name is not None:
if not GroupDescr.check_name(group.partition, group_name, existing=True): if not GroupDescr.check_name(group.partition, group_name, existing=True):
return error_response(404, "invalid group_name") return json_error(404, "invalid group_name")
group.group_name = group_name.strip() group.group_name = group_name.strip()
db.session.add(group) db.session.add(group)
db.session.commit() db.session.commit()
@ -358,14 +358,14 @@ def partition_create(formsemestre_id: int):
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
partition_name = data.get("partition_name") partition_name = data.get("partition_name")
if partition_name is None: if partition_name is None:
return error_response(404, "missing partition_name or invalid data format") return json_error(404, "missing partition_name or invalid data format")
if partition_name == scu.PARTITION_PARCOURS: if partition_name == scu.PARTITION_PARCOURS:
return error_response(404, f"invalid partition_name {scu.PARTITION_PARCOURS}") return json_error(404, f"invalid partition_name {scu.PARTITION_PARCOURS}")
if not Partition.check_name(formsemestre, partition_name): if not Partition.check_name(formsemestre, partition_name):
return error_response(404, "invalid partition_name") return json_error(404, "invalid partition_name")
numero = data.get("numero", 0) numero = data.get("numero", 0)
if not isinstance(numero, int): if not isinstance(numero, int):
return error_response(404, "invalid type for numero") return json_error(404, "invalid type for numero")
args = { args = {
"formsemestre_id": formsemestre_id, "formsemestre_id": formsemestre_id,
"partition_name": partition_name.strip(), "partition_name": partition_name.strip(),
@ -376,7 +376,7 @@ def partition_create(formsemestre_id: int):
boolean_field, False if boolean_field != "groups_editable" else True boolean_field, False if boolean_field != "groups_editable" else True
) )
if not isinstance(value, bool): if not isinstance(value, bool):
return error_response(404, f"invalid type for {boolean_field}") return json_error(404, f"invalid type for {boolean_field}")
args[boolean_field] = value args[boolean_field] = value
partition = Partition(**args) partition = Partition(**args)
@ -407,7 +407,7 @@ def formsemestre_order_partitions(formsemestre_id: int):
if not isinstance(partition_ids, int) and not all( if not isinstance(partition_ids, int) and not all(
isinstance(x, int) for x in partition_ids isinstance(x, int) for x in partition_ids
): ):
return error_response( return json_error(
404, 404,
message="paramètre liste des partitions invalide", message="paramètre liste des partitions invalide",
) )
@ -444,7 +444,7 @@ def partition_order_groups(partition_id: int):
if not isinstance(group_ids, int) and not all( if not isinstance(group_ids, int) and not all(
isinstance(x, int) for x in group_ids isinstance(x, int) for x in group_ids
): ):
return error_response( return json_error(
404, 404,
message="paramètre liste de groupe invalide", message="paramètre liste de groupe invalide",
) )
@ -487,18 +487,18 @@ def partition_edit(partition_id: int):
# #
if partition_name is not None and partition_name != partition.partition_name: if partition_name is not None and partition_name != partition.partition_name:
if partition.is_parcours(): if partition.is_parcours():
return error_response(404, f"can't rename {scu.PARTITION_PARCOURS}") return json_error(404, f"can't rename {scu.PARTITION_PARCOURS}")
if not Partition.check_name( if not Partition.check_name(
partition.formsemestre, partition_name, existing=True partition.formsemestre, partition_name, existing=True
): ):
return error_response(404, "invalid partition_name") return json_error(404, "invalid partition_name")
partition.partition_name = partition_name.strip() partition.partition_name = partition_name.strip()
modified = True modified = True
numero = data.get("numero") numero = data.get("numero")
if numero is not None and numero != partition.numero: if numero is not None and numero != partition.numero:
if not isinstance(numero, int): if not isinstance(numero, int):
return error_response(404, "invalid type for numero") return json_error(404, "invalid type for numero")
partition.numero = numero partition.numero = numero
modified = True modified = True
@ -506,9 +506,9 @@ def partition_edit(partition_id: int):
value = data.get(boolean_field) value = data.get(boolean_field)
if value is not None and value != getattr(partition, boolean_field): if value is not None and value != getattr(partition, boolean_field):
if not isinstance(value, bool): if not isinstance(value, bool):
return error_response(404, f"invalid type for {boolean_field}") return json_error(404, f"invalid type for {boolean_field}")
if boolean_field == "groups_editable" and partition.is_parcours(): if boolean_field == "groups_editable" and partition.is_parcours():
return error_response(404, f"can't change {scu.PARTITION_PARCOURS}") return json_error(404, f"can't change {scu.PARTITION_PARCOURS}")
setattr(partition, boolean_field, value) setattr(partition, boolean_field, value)
modified = True modified = True
@ -540,7 +540,7 @@ def partition_delete(partition_id: int):
query = query.join(FormSemestre).filter_by(dept_id=g.scodoc_dept_id) query = query.join(FormSemestre).filter_by(dept_id=g.scodoc_dept_id)
partition: Partition = query.first_or_404() partition: Partition = query.first_or_404()
if not partition.partition_name: if not partition.partition_name:
return error_response(404, "ne peut pas supprimer la partition par défaut") return json_error(404, "ne peut pas supprimer la partition par défaut")
is_parcours = partition.is_parcours() is_parcours = partition.is_parcours()
formsemestre: FormSemestre = partition.formsemestre formsemestre: FormSemestre = partition.formsemestre
log(f"deleting partition {partition}") log(f"deleting partition {partition}")

View File

@ -10,7 +10,7 @@ from flask_login import current_user
from sqlalchemy import desc, or_ from sqlalchemy import desc, or_
from app import models from app import models
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.models import Departement, Identite, Admission from app.models import Departement, Identite, Admission
from app.scodoc.sco_permissions import Permission from app.scodoc.sco_permissions import Permission
@ -39,7 +39,7 @@ def get_etud(etudid=None, nip=None, ine=None) -> models.Identite:
elif ine is not None: elif ine is not None:
query = Identite.query.filter_by(code_ine=ine) query = Identite.query.filter_by(code_ine=ine)
else: else:
return error_response( return json_error(
404, 404,
message="parametre manquant", message="parametre manquant",
) )

View File

@ -12,10 +12,10 @@
from flask import g, jsonify, request from flask import g, jsonify, request
from flask_login import current_user, login_required from flask_login import current_user, login_required
import app
from app import db, log from app import db, log
from app.api import api_bp as bp, api_web_bp from app.api import api_bp as bp, api_web_bp
from app.api.errors import error_response from app.models.etudiants import Identite
from app.scodoc.sco_utils import json_error
from app.auth.models import User, Role, UserRole from app.auth.models import User, Role, UserRole
from app.decorators import scodoc, permission_required from app.decorators import scodoc, permission_required
from app.models import Departement from app.models import Departement
@ -35,11 +35,11 @@ def user_info(uid: int):
""" """
user: User = User.query.get(uid) user: User = User.query.get(uid)
if user is None: if user is None:
return error_response(404, "user not found") return json_error(404, "user not found")
if g.scodoc_dept: if g.scodoc_dept:
allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersView) allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersView)
if user.dept not in allowed_depts: if user.dept not in allowed_depts:
return error_response(404, "user not found") return json_error(404, "user not found")
return jsonify(user.to_dict()) return jsonify(user.to_dict())
@ -101,20 +101,20 @@ def user_create():
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
user_name = data.get("user_name") user_name = data.get("user_name")
if not user_name: if not user_name:
return error_response(404, "empty user_name") return json_error(404, "empty user_name")
user = User.query.filter_by(user_name=user_name).first() user = User.query.filter_by(user_name=user_name).first()
if user: if user:
return error_response(404, f"user_create: user {user} already exists\n") return json_error(404, f"user_create: user {user} already exists\n")
dept = data.get("dept") dept = data.get("dept")
if dept == "@all": if dept == "@all":
dept = None dept = None
allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersAdmin) allowed_depts = current_user.get_depts_with_permission(Permission.ScoUsersAdmin)
if dept not in allowed_depts: if dept not in allowed_depts:
return error_response(403, "user_create: departement non autorise") return json_error(403, "user_create: departement non autorise")
if (dept is not None) and ( if (dept is not None) and (
Departement.query.filter_by(acronym=dept).first() is None Departement.query.filter_by(acronym=dept).first() is None
): ):
return error_response(404, "user_create: departement inexistant") return json_error(404, "user_create: departement inexistant")
nom = data.get("nom") nom = data.get("nom")
prenom = data.get("prenom") prenom = data.get("prenom")
active = scu.to_bool(data.get("active", True)) active = scu.to_bool(data.get("active", True))
@ -151,12 +151,12 @@ def user_edit(uid: int):
if (None not in allowed_depts) and ( if (None not in allowed_depts) and (
(orig_dept not in allowed_depts) or (dest_dept not in allowed_depts) (orig_dept not in allowed_depts) or (dest_dept not in allowed_depts)
): ):
return error_response(403, "user_edit: departement non autorise") return json_error(403, "user_edit: departement non autorise")
if dest_dept != orig_dept: if dest_dept != orig_dept:
if (dest_dept is not None) and ( if (dest_dept is not None) and (
Departement.query.filter_by(acronym=dest_dept).first() is None Departement.query.filter_by(acronym=dest_dept).first() is None
): ):
return error_response(404, "user_edit: departement inexistant") return json_error(404, "user_edit: departement inexistant")
user.dept = dest_dept user.dept = dest_dept
user.nom = data.get("nom", user.nom) user.nom = data.get("nom", user.nom)
@ -189,7 +189,7 @@ def user_role_add(uid: int, role_name: str, dept: str = None):
_ = Departement.query.filter_by(acronym=dept).first_or_404() _ = Departement.query.filter_by(acronym=dept).first_or_404()
allowed_depts = current_user.get_depts_with_permission(Permission.ScoSuperAdmin) allowed_depts = current_user.get_depts_with_permission(Permission.ScoSuperAdmin)
if (None not in allowed_depts) and (dept not in allowed_depts): if (None not in allowed_depts) and (dept not in allowed_depts):
return error_response(403, "user_role_add: departement non autorise") return json_error(403, "user_role_add: departement non autorise")
user.add_role(role, dept) user.add_role(role, dept)
db.session.add(user) db.session.add(user)
db.session.commit() db.session.commit()
@ -217,7 +217,7 @@ def user_role_remove(uid: int, role_name: str, dept: str = None):
_ = Departement.query.filter_by(acronym=dept).first_or_404() _ = Departement.query.filter_by(acronym=dept).first_or_404()
allowed_depts = current_user.get_depts_with_permission(Permission.ScoSuperAdmin) allowed_depts = current_user.get_depts_with_permission(Permission.ScoSuperAdmin)
if (None not in allowed_depts) and (dept not in allowed_depts): if (None not in allowed_depts) and (dept not in allowed_depts):
return error_response(403, "user_role_remove: departement non autorise") return json_error(403, "user_role_remove: departement non autorise")
query = UserRole.query.filter(UserRole.role == role, UserRole.user == user) query = UserRole.query.filter(UserRole.role == role, UserRole.user == user)
if dept is not None: if dept is not None:
@ -276,7 +276,7 @@ def role_permission_add(role_name: str, perm_name: str):
role: Role = Role.query.filter_by(name=role_name).first_or_404() role: Role = Role.query.filter_by(name=role_name).first_or_404()
permission = Permission.get_by_name(perm_name) permission = Permission.get_by_name(perm_name)
if permission is None: if permission is None:
return error_response(404, "role_permission_add: permission inconnue") return json_error(404, "role_permission_add: permission inconnue")
role.add_permission(permission) role.add_permission(permission)
db.session.add(role) db.session.add(role)
db.session.commit() db.session.commit()
@ -299,7 +299,7 @@ def role_permission_remove(role_name: str, perm_name: str):
role: Role = Role.query.filter_by(name=role_name).first_or_404() role: Role = Role.query.filter_by(name=role_name).first_or_404()
permission = Permission.get_by_name(perm_name) permission = Permission.get_by_name(perm_name)
if permission is None: if permission is None:
return error_response(404, "role_permission_remove: permission inconnue") return json_error(404, "role_permission_remove: permission inconnue")
role.remove_permission(permission) role.remove_permission(permission)
db.session.add(role) db.session.add(role)
db.session.commit() db.session.commit()
@ -319,7 +319,7 @@ def role_create(role_name: str):
""" """
role: Role = Role.query.filter_by(name=role_name).first() role: Role = Role.query.filter_by(name=role_name).first()
if role: if role:
return error_response(404, "role_create: role already exists") return json_error(404, "role_create: role already exists")
role = Role(name=role_name) role = Role(name=role_name)
data = request.get_json(force=True) # may raise 400 Bad Request data = request.get_json(force=True) # may raise 400 Bad Request
permissions = data.get("permissions") permissions = data.get("permissions")
@ -327,7 +327,7 @@ def role_create(role_name: str):
try: try:
role.set_named_permissions(permissions) role.set_named_permissions(permissions)
except ScoValueError: except ScoValueError:
return error_response(404, "role_create: invalid permissions") return json_error(404, "role_create: invalid permissions")
db.session.add(role) db.session.add(role)
db.session.commit() db.session.commit()
return jsonify(role.to_dict()) return jsonify(role.to_dict())
@ -352,12 +352,12 @@ def role_edit(role_name: str):
try: try:
role.set_named_permissions(permissions) role.set_named_permissions(permissions)
except ScoValueError: except ScoValueError:
return error_response(404, "role_create: invalid permissions") return json_error(404, "role_create: invalid permissions")
role_name = data.get("role_name") role_name = data.get("role_name")
if role_name and role_name != role.name: if role_name and role_name != role.name:
existing_role: Role = Role.query.filter_by(name=role_name).first() existing_role: Role = Role.query.filter_by(name=role_name).first()
if existing_role: if existing_role:
return error_response(404, "role_edit: role name already exists") return json_error(404, "role_edit: role name already exists")
role.name = role_name role.name = role_name
db.session.add(role) db.session.add(role)
db.session.commit() db.session.commit()

View File

@ -9,7 +9,7 @@ from flask import g, redirect, request, url_for
from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth
import flask_login import flask_login
from app import login from app import login
from app.api.errors import error_response from app.scodoc.sco_utils import json_error
from app.auth.models import User from app.auth.models import User
basic_auth = HTTPBasicAuth() basic_auth = HTTPBasicAuth()
@ -80,8 +80,6 @@ def load_user_from_request(req: flask.Request) -> User:
@login.unauthorized_handler @login.unauthorized_handler
def unauthorized(): def unauthorized():
"flask-login: si pas autorisé, redirige vers page login, sauf si API" "flask-login: si pas autorisé, redirige vers page login, sauf si API"
from app.api.errors import error_response as api_error_response
if request.blueprint == "api" or request.blueprint == "apiweb": if request.blueprint == "api" or request.blueprint == "apiweb":
return api_error_response(http.HTTPStatus.UNAUTHORIZED, "Non autorise (logic)") return json_error(http.HTTPStatus.UNAUTHORIZED, "Non autorise (logic)")
return redirect(url_for("auth.login")) return redirect(url_for("auth.login"))

View File

@ -10,11 +10,10 @@
import collections import collections
import datetime import datetime
import numpy as np import numpy as np
from flask import url_for, g from flask import g, has_request_context, url_for
from app.comp.res_but import ResultatsSemestreBUT from app.comp.res_but import ResultatsSemestreBUT
from app.models import FormSemestre, Identite from app.models import FormSemestre, Identite
from app.models import but_validations
from app.models.groups import GroupDescr from app.models.groups import GroupDescr
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.scodoc import sco_bulletins, sco_utils as scu from app.scodoc import sco_bulletins, sco_utils as scu
@ -170,7 +169,9 @@ class BulletinBUT:
"notes.moduleimpl_status", "notes.moduleimpl_status",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
moduleimpl_id=modimpl.id, moduleimpl_id=modimpl.id,
), )
if has_request_context()
else "na",
"moyenne": { "moyenne": {
# # moyenne indicative de module: moyenne des UE, # # moyenne indicative de module: moyenne des UE,
# # ignorant celles sans notes (nan) # # ignorant celles sans notes (nan)
@ -228,7 +229,9 @@ class BulletinBUT:
"notes.evaluation_listenotes", "notes.evaluation_listenotes",
scodoc_dept=g.scodoc_dept, scodoc_dept=g.scodoc_dept,
evaluation_id=e.id, evaluation_id=e.id,
), )
if has_request_context()
else "na",
} }
return d return d

View File

@ -6,7 +6,7 @@
import datetime import datetime
from functools import cached_property from functools import cached_property
from flask import abort, url_for from flask import abort, has_request_context, url_for
from flask import g, request from flask import g, request
import sqlalchemy import sqlalchemy
from sqlalchemy import desc, text from sqlalchemy import desc, text
@ -196,7 +196,8 @@ class Identite(db.Model):
"nationalite": self.nationalite or "", "nationalite": self.nationalite or "",
"boursier": self.boursier or "", "boursier": self.boursier or "",
} }
if include_urls: if include_urls and has_request_context():
# test request context so we can use this func in tests under the flask shell
d["fiche_url"] = url_for( d["fiche_url"] = url_for(
"scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=self.id "scolar.ficheEtud", scodoc_dept=g.scodoc_dept, etudid=self.id
) )

View File

@ -37,6 +37,7 @@ from flask_login import current_user
from app import email from app import email
from app import log from app import log
from app.scodoc.sco_utils import json_error
from app.but import bulletin_but from app.but import bulletin_but
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
@ -74,9 +75,13 @@ def get_formsemestre_bulletin_etud_json(
) -> str: ) -> str:
"""Le JSON du bulletin d'un étudiant, quel que soit le type de formation.""" """Le JSON du bulletin d'un étudiant, quel que soit le type de formation."""
if formsemestre.formation.is_apc(): if formsemestre.formation.is_apc():
r = bulletin_but.BulletinBUT(formsemestre) bul = bulletin_but.BulletinBUT(formsemestre)
if not etud.id in bul.res.identdict:
return error_response(
404, "get_formsemestre_bulletin_etud_json: invalid etud"
)
return jsonify( return jsonify(
r.bulletin_etud( bul.bulletin_etud(
etud, etud,
formsemestre, formsemestre,
force_publishing=force_publishing, force_publishing=force_publishing,

View File

@ -53,6 +53,7 @@ import requests
import flask import flask
from flask import g, request from flask import g, request
from flask import flash, url_for, make_response, jsonify from flask import flash, url_for, make_response, jsonify
from werkzeug.http import HTTP_STATUS_CODES
from config import Config from config import Config
from app import log from app import log
@ -819,15 +820,26 @@ def get_request_args():
return vals return vals
def json_error(message, success=False, status=404): def json_error(status_code, message=None):
"""Simple JSON response, for errors""" """Simple JSON response, for errors"""
response = { payload = {
"success": success, "error": HTTP_STATUS_CODES.get(status_code, "Unknown error"),
"status": status, "status": status_code,
"message": message,
} }
if message:
payload["message"] = message
response = jsonify(payload)
response.status_code = status_code
log(f"Error: {response}") log(f"Error: {response}")
return jsonify(response), status return response
def json_ok_response(status_code=200, payload=None):
"""Simple JSON respons for "success" """
payload = payload or {"OK": True}
response = jsonify(payload)
response.status_code = status_code
return response
def get_scodoc_version(): def get_scodoc_version():

View File

@ -36,17 +36,22 @@ import time
from xml.etree import ElementTree from xml.etree import ElementTree
import flask import flask
from flask import abort, flash, jsonify, redirect, render_template, url_for from flask import abort, flash, redirect, render_template, url_for
from flask import current_app, g, request from flask import current_app, g, request
from flask_login import current_user from flask_login import current_user
from app import db
from app import models
from app.auth.models import User
from app.but import apc_edit_ue, jury_but_recap
from app.but import jury_but, jury_but_validation_auto from app.but import jury_but, jury_but_validation_auto
from app.but.forms import jury_but_forms from app.but.forms import jury_but_forms
from app.but import jury_but_pv from app.but import jury_but_pv
from app.but import jury_but_view from app.but import jury_but_view
from app.comp import res_sem from app.comp import res_sem
from app.comp.res_but import ResultatsSemestreBUT
from app.comp.res_compat import NotesTableCompat from app.comp.res_compat import NotesTableCompat
from app.models import ScolarNews
from app.models.config import ScoDocSiteConfig from app.models.config import ScoDocSiteConfig
from app.models.etudiants import Identite from app.models.etudiants import Identite
from app.models.formsemestre import FormSemestre from app.models.formsemestre import FormSemestre
@ -54,13 +59,8 @@ from app.models.formsemestre import FormSemestreUEComputationExpr
from app.models.moduleimpls import ModuleImpl from app.models.moduleimpls import ModuleImpl
from app.models.modules import Module from app.models.modules import Module
from app.models.ues import UniteEns from app.models.ues import UniteEns
from app.views import notes_bp as bp
from app import api
from app import db
from app import models
from app.models import ScolarNews, but_validations
from app.auth.models import User
from app.but import apc_edit_ue, jury_but_recap
from app.decorators import ( from app.decorators import (
scodoc, scodoc,
scodoc7func, scodoc7func,
@ -68,7 +68,6 @@ from app.decorators import (
permission_required_compat_scodoc7, permission_required_compat_scodoc7,
) )
from app.views import notes_bp as bp
# --------------- # ---------------
@ -775,7 +774,7 @@ def formsemestre_list(
formsemestre_id = int(formsemestre_id) if formsemestre_id is not None else None formsemestre_id = int(formsemestre_id) if formsemestre_id is not None else None
formation_id = int(formation_id) if formation_id is not None else None formation_id = int(formation_id) if formation_id is not None else None
except ValueError: except ValueError:
return api.errors.error_response(404, "invalid id") return scu.json_error(404, "invalid id")
# XAPI: new json api # XAPI: new json api
args = {} args = {}
L = locals() L = locals()

View File

@ -128,26 +128,26 @@ def set_module_ue_coef():
try: try:
module_id = int(request.form["module_id"]) module_id = int(request.form["module_id"])
except ValueError: except ValueError:
return scu.json_error("invalid module_id", 400) return scu.json_error(404, "invalid module_id")
try: try:
ue_id = int(request.form["ue_id"]) ue_id = int(request.form["ue_id"])
except ValueError: except ValueError:
return scu.json_error("invalid ue_id", 400) return scu.json_error(404, "invalid ue_id")
try: try:
coef = float(request.form["coef"].replace(",", ".")) coef = float(request.form["coef"].replace(",", "."))
except ValueError: except ValueError:
return scu.json_error("invalid coef", 400) return scu.json_error(404, "invalid coef")
module = models.Module.query.get(module_id) module = models.Module.query.get(module_id)
if module is None: if module is None:
return scu.json_error(f"module not found ({module_id})", 404) return scu.json_error(404, f"module not found ({module_id})")
ue = models.UniteEns.query.get(ue_id) ue = models.UniteEns.query.get(ue_id)
if not ue: if not ue:
return scu.json_error(f"UE not found ({ue_id})", 404) return scu.json_error(404, f"UE not found ({ue_id})")
module.set_ue_coef(ue, coef) module.set_ue_coef(ue, coef)
db.session.commit() db.session.commit()
module.formation.invalidate_cached_sems() module.formation.invalidate_cached_sems()
return scu.json_error("ok", success=True, status=201) return scu.json_ok_response(201)
@bp.route("/edit_modules_ue_coefs") @bp.route("/edit_modules_ue_coefs")

View File

@ -55,24 +55,24 @@ class APIError(Exception):
pass pass
def GET(path: str, headers={}, errmsg=None, dept=None): def GET(path: str, headers: dict = None, errmsg=None, dept=None):
"""Get and returns as JSON""" """Get and returns as JSON"""
if dept: if dept:
url = SCODOC_URL + f"/ScoDoc/{dept}/api" + path url = SCODOC_URL + f"/ScoDoc/{dept}/api" + path
else: else:
url = API_URL + path url = API_URL + path
r = requests.get(url, headers=headers or CUR_HEADERS, verify=CHECK_CERTIFICATE) r = requests.get(url, headers=headers or {}, verify=CHECK_CERTIFICATE)
if r.status_code != 200: if r.status_code != 200:
raise APIError(errmsg or f"""erreur status={r.status_code} !\n{r.text}""") raise APIError(errmsg or f"""erreur status={r.status_code} !\n{r.text}""")
return r.json() # decode la reponse JSON return r.json() # decode la reponse JSON
def POST_JSON(path: str, data: dict = {}, headers={}, errmsg=None): def POST_JSON(path: str, data: dict = {}, headers: dict = None, errmsg=None):
"""Post""" """Post"""
r = requests.post( r = requests.post(
API_URL + path, API_URL + path,
json=data, json=data,
headers=headers, headers=headers or {},
verify=CHECK_CERTIFICATE, verify=CHECK_CERTIFICATE,
) )
if r.status_code != 200: if r.status_code != 200:

View File

@ -46,7 +46,7 @@ def test_admin_access(create_admin_token):
headers = {"Authorization": f"Bearer {token}"} headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client: with app.test_client() as client:
response = client.get(API_URL + "/logos", headers=headers) response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 401 assert response.status_code == 403
def test_lambda_access(create_lambda_token): def test_lambda_access(create_lambda_token):
@ -57,7 +57,7 @@ def test_lambda_access(create_lambda_token):
headers = {"Authorization": f"Bearer {token}"} headers = {"Authorization": f"Bearer {token}"}
with app.test_client() as client: with app.test_client() as client:
response = client.get(API_URL + "/logos", headers=headers) response = client.get(API_URL + "/logos", headers=headers)
assert response.status_code == 401 assert response.status_code == 403
def test_initial_with_header_and_footer(create_super_token): def test_initial_with_header_and_footer(create_super_token):

View File

@ -201,33 +201,23 @@ def create_formsemestre(
def inscrit_etudiants(etuds: list, formsemestre: FormSemestre): def inscrit_etudiants(etuds: list, formsemestre: FormSemestre):
"""Inscrit les etudiants aux semestres et à tous ses modules""" """Inscrit les étudiants au semestre et à tous ses modules.
for etud in etuds: 1/5 DEF, 1/5 DEF
aleatoire = random.randint(0, 10) """
if aleatoire <= 3: for i, etud in enumerate(etuds):
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( if (i + 1) % 5 == 0:
formsemestre.id, etat = "D"
etud.id, elif (i + 2) % 5 == 0:
group_ids=[], etat = "DEF"
etat="I",
method="init db test",
)
elif 3 < aleatoire <= 6:
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
formsemestre.id,
etud.id,
group_ids=[],
etat="D",
method="init db test",
)
else: else:
sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules( etat = "I"
formsemestre.id, sco_formsemestre_inscriptions.do_formsemestre_inscription_with_modules(
etud.id, formsemestre.id,
group_ids=[], etud.id,
etat="DEF", group_ids=[],
method="init db test", etat=etat,
) method="init db test",
)
def create_evaluations(formsemestre: FormSemestre): def create_evaluations(formsemestre: FormSemestre):
@ -368,11 +358,11 @@ def init_test_database():
mapp.set_sco_dept(dept.acronym) mapp.set_sco_dept(dept.acronym)
user_lecteur, user_autre = create_users(depts) user_lecteur, user_autre = create_users(depts)
with sco_cache.DeferredSemCacheManager(): with sco_cache.DeferredSemCacheManager():
etuds = create_etuds(dept) etuds = create_etuds(dept, nb=20)
formation = import_formation(dept.id) formation = import_formation(dept.id)
formsemestre = create_formsemestre(formation, user_lecteur) formsemestre = create_formsemestre(formation, user_lecteur)
create_evaluations(formsemestre) create_evaluations(formsemestre)
inscrit_etudiants(etuds, formsemestre) inscrit_etudiants(etuds[:16], formsemestre)
saisie_notes_evaluations(formsemestre, user_lecteur) saisie_notes_evaluations(formsemestre, user_lecteur)
add_absences(formsemestre) add_absences(formsemestre)
create_etape_apo(formsemestre) create_etape_apo(formsemestre)