API: modif formsemestre/etudiant. TESTS unitaires OK sauf logos.

This commit is contained in:
Emmanuel Viennet 2022-08-08 10:06:42 +02:00
parent f7a2c1e8e7
commit c065abd0bb
8 changed files with 79 additions and 143 deletions

View File

@ -19,15 +19,13 @@ from app.scodoc import sco_abs
from app.scodoc.sco_groups import get_group_members
from app.scodoc.sco_permissions import Permission
# TODO XXX revoir routes web API et calcul des droits
@bp.route("/absences/etudid/<int:etudid>", methods=["GET"])
@scodoc
@permission_required(Permission.ScoView)
def absences(etudid: int = None):
"""
Retourne la liste des absences d'un étudiant donné
etudid : l'etudid d'un étudiant
Liste des absences de cet étudiant
Exemple de résultat:
[

View File

@ -31,16 +31,16 @@ from app.scodoc.sco_bulletins import do_formsemestre_bulletinetud
from app.scodoc.sco_permissions import Permission
# Un exemple:
@bp.route("/api_function/<int:arg>")
@api_web_bp.route("/api_function/<int:arg>")
@login_required
@scodoc
@permission_required(Permission.ScoView)
def api_function(arg: int):
"""Une fonction quelconque de l'API"""
return jsonify(
{"current_user": current_user.to_dict(), "arg": arg, "dept": g.scodoc_dept}
)
# @bp.route("/api_function/<int:arg>")
# @api_web_bp.route("/api_function/<int:arg>")
# @login_required
# @scodoc
# @permission_required(Permission.ScoView)
# def api_function(arg: int):
# """Une fonction quelconque de l'API"""
# return jsonify(
# {"current_user": current_user.to_dict(), "arg": arg, "dept": g.scodoc_dept}
# )
@bp.route("/etudiants/courants", defaults={"long": False})

View File

@ -251,6 +251,10 @@ def formsemestre_programme(formsemestre_id: int):
@bp.route(
"/formsemestre/<int:formsemestre_id>/etudiants",
defaults={"etat": None},
)
@bp.route(
"/formsemestre/<int:formsemestre_id>/etudiants/actifs",
defaults={"etat": scu.INSCRIT},
)
@bp.route(
@ -263,6 +267,10 @@ def formsemestre_programme(formsemestre_id: int):
)
@api_web_bp.route(
"/formsemestre/<int:formsemestre_id>/etudiants",
defaults={"etat": None},
)
@api_web_bp.route(
"/formsemestre/<int:formsemestre_id>/etudiants/actifs",
defaults={"etat": scu.INSCRIT},
)
@api_web_bp.route(
@ -276,18 +284,17 @@ def formsemestre_programme(formsemestre_id: int):
@login_required
@scodoc
@permission_required(Permission.ScoView)
def formsemestre_etudiants(formsemestre_id: int, etat: str):
"""
Retourne la liste des étudiants d'un formsemestre
formsemestre_id : l'id d'un formsemestre
"""
def formsemestre_etudiants(formsemestre_id: int, etat: str = None):
"""Etudiants d'un formsemestre."""
query = FormSemestre.query.filter_by(id=formsemestre_id)
if g.scodoc_dept:
query = query.filter_by(dept_id=g.scodoc_dept_id)
formsemestre: FormSemestre = query.first_or_404(formsemestre_id)
if etat is None:
inscriptions = formsemestre.inscriptions
else:
inscriptions = [ins for ins in formsemestre.inscriptions if ins.etat == etat]
inscriptions = [ins for ins in formsemestre.inscriptions if ins.etat == etat]
etuds = [ins.etud.to_dict_short() for ins in inscriptions]
# Ajout des groupes de chaque étudiants
# XXX A REVOIR: trop inefficace !

View File

@ -53,8 +53,8 @@ def users_info_query():
"""Utilisateurs, filtrés par dept, active ou début nom
/users/query?departement=dept_acronym&active=1&starts_with=<string:nom>
Si accès via API web, seuls les utilisateurs "accessibles" (selon les
permissions) sont retournés: le département de l'URL est ignoré, seules
Seuls les utilisateurs "accessibles" (selon les permissions) sont retournés.
Si accès via API web, le département de l'URL est ignoré, seules
les permissions de l'utilisateur sont prises en compte.
"""
query = User.query

View File

@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
"""Test Logos
"""Test formsemestre
Utilisation :
créer les variables d'environnement: (indiquer les valeurs
@ -481,32 +481,17 @@ def test_bulletins(api_headers):
assert isinstance(bulletin_semestre["rang"]["total"], int)
# # jury
# def test_jury():
# r = requests.get(
# API_URL + "/formsemestre/1/jury",
# headers=api_headers,
# verify=CHECK_CERTIFICATE,
# )
# assert r.status_code == 200
def test_formsemestre_etudiants(api_headers):
"""
Route: /formsemestre/<int:formsemestre_id>/etudiants,
/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires,
Route: /formsemestre/<int:formsemestre_id>/etudiants
/formsemestre/<int:formsemestre_id>/etudiants/actifs
/formsemestre/<int:formsemestre_id>/etudiants/demissionnaires
/formsemestre/<int:formsemestre_id>/etudiants/defaillants
"""
formsemestre_id = 1
r = requests.get(
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
formsemestre_etus = r.json()
assert isinstance(formsemestre_etus, list)
for etud in formsemestre_etus:
etuds = GET(f"/formsemestre/{formsemestre_id}/etudiants", headers=api_headers)
assert isinstance(etuds, list)
for etud in etuds:
assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True
assert isinstance(etud["id"], int)
assert isinstance(etud["code_nip"], str)
@ -530,77 +515,26 @@ def test_formsemestre_etudiants(api_headers):
assert isinstance(group["group_id"], int)
assert group["group_name"] is None or isinstance(group["group_name"], int)
### demissionnaires ###
r_demissionnaires = requests.get(
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants/demissionnaires",
headers=api_headers,
verify=CHECK_CERTIFICATE,
### actifs
etuds_actifs = GET(
f"/formsemestre/{formsemestre_id}/etudiants/actifs", headers=api_headers
)
assert r_demissionnaires.status_code == 200
formsemestre_etus = r_demissionnaires.json()
assert isinstance(formsemestre_etus, list)
assert isinstance(etuds_actifs, list)
for etud in formsemestre_etus:
assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True
assert isinstance(etud["id"], int)
assert isinstance(etud["code_nip"], str)
assert isinstance(etud["code_ine"], str)
assert isinstance(etud["nom"], str)
assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str)
assert isinstance(etud["prenom"], str)
assert isinstance(etud["civilite"], str)
assert isinstance(etud["groups"], list)
etu_groups = etud["groups"]
for group in etu_groups:
assert isinstance(group["partition_id"], int)
assert isinstance(group["id"], int)
assert isinstance(group["formsemestre_id"], int)
assert group["partition_name"] is None or isinstance(
group["partition_name"], str
)
assert (group["numero"] is None) or isinstance(group["numero"], int)
assert isinstance(group["bul_show_rank"], bool)
assert isinstance(group["show_in_lists"], bool)
assert isinstance(group["group_id"], int)
assert group["group_name"] is None or isinstance(group["group_name"], int)
### defaillants ###
r_defaillants = requests.get(
f"{API_URL}/formsemestre/{formsemestre_id}/etudiants/defaillants",
### démissionnaires
etuds_dem = GET(
f"/formsemestre/{formsemestre_id}/etudiants/demissionnaires",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r_defaillants.status_code == 200
assert isinstance(etuds_dem, list)
formsemestre_etus = r_defaillants.json()
assert isinstance(formsemestre_etus, list)
for etud in formsemestre_etus:
assert verify_fields(etud, FORMSEMESTRE_ETUD_FIELDS) is True
assert isinstance(etud["id"], int)
assert isinstance(etud["code_nip"], str)
assert isinstance(etud["code_ine"], str)
assert isinstance(etud["nom"], str)
assert etud["nom_usuel"] is None or isinstance(etud["nom_usuel"], str)
assert isinstance(etud["prenom"], str)
assert isinstance(etud["civilite"], str)
assert isinstance(etud["groups"], list)
etu_groups = etud["groups"]
for group in etu_groups:
assert isinstance(group["partition_id"], int)
assert isinstance(group["id"], int)
assert isinstance(group["formsemestre_id"], int)
assert group["partition_name"] is None or isinstance(
group["partition_name"], str
)
assert (group["numero"] is None) or isinstance(group["numero"], int)
assert isinstance(group["bul_show_rank"], bool)
assert isinstance(group["show_in_lists"], bool)
assert isinstance(group["group_id"], int)
assert group["group_name"] is None or isinstance(group["group_name"], int)
### défaillants
etuds_def = GET(
f"/formsemestre/{formsemestre_id}/etudiants/defaillants", headers=api_headers
)
assert isinstance(etuds_def, list)
assert r.json() != r_demissionnaires.json()
assert r.json() != r_defaillants.json()
assert r_demissionnaires.json() != r_defaillants.json()
assert len(etuds) == (len(etuds_actifs) + len(etuds_dem) + len(etuds_def))
### ERROR ###
id_formsemestre_inexistant = 265165689619851621685

View File

@ -17,37 +17,24 @@ Utilisation :
pytest tests/api/test_api_jury.py
"""
import requests
from tests.api.setup_test_api import API_URL, CHECK_CERTIFICATE, api_headers
def test_jury_preparation(api_headers):
"""
Test 'jury_preparation'
Route :
- /jury/formsemestre/<int:formsemestre_id>/preparation_jury
"""
r = requests.get(
API_URL
+ "/ScoDoc/api/jury/formsemestre/<int:formsemestre_id>/preparation_jury",
headers=api_headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 200
from tests.api.setup_test_api import (
API_URL,
CHECK_CERTIFICATE,
GET,
POST_JSON,
api_headers,
)
def test_jury_decisions(api_headers):
"""
Test 'jury_decisions'
Route :
- /jury/formsemestre/<int:formsemestre_id>/decisions_jury
- /formsemestre/<int:formsemestre_id>/decisions_jury
"""
r = requests.get(
API_URL + "/jury/formsemestre/<int:formsemestre_id>/decisions_jury",
headers=api_headers,
verify=CHECK_CERTIFICATE,
formsemestre_id = 1
etudiants = GET(f"/formsemestre/{formsemestre_id}/etudiants", headers=api_headers)
decisions_jury = GET(
f"/formsemestre/{formsemestre_id}/decisions_jury", headers=api_headers
)
assert r.status_code == 200
assert len(etudiants) == len(decisions_jury)

View File

@ -13,7 +13,6 @@
import requests
import flask
from tests.api.setup_test_api import API_URL, SCODOC_URL, CHECK_CERTIFICATE, api_headers
from tests.api.tools_test_api import verify_fields
@ -35,16 +34,18 @@ def test_permissions(api_headers):
for r in app.url_map.iter_rules()
if str(r).startswith("/ScoDoc/api")
and not "logo" in str(r) # ignore logos
and not "absence" in str(r) # ignore absences
and "GET" in r.methods
]
assert len(api_rules) > 0
args = {
"etudid": 1,
"dept": "TAPI",
"dept_ident": "TAPI",
"acronym": "TAPI",
"dept_id": 1,
"dept_ident": "TAPI",
"dept": "TAPI",
"etape_apo": "???",
"etat": "I",
"etudid": 1,
"evaluation_id": 1,
"formation_id": 1,
"formsemestre_id": 1,
@ -54,6 +55,8 @@ def test_permissions(api_headers):
"moduleimpl_id": 1,
"nip": 1,
"partition_id": 1,
"role_name": "Ens",
"uid": 1,
}
for rule in api_rules:
path = rule.build(args)[1]
@ -95,4 +98,4 @@ def test_permissions(api_headers):
headers=headers,
verify=CHECK_CERTIFICATE,
)
assert r.status_code == 403
assert r.status_code == 401

View File

@ -84,6 +84,8 @@ def create_users(depts: list[Departement]) -> tuple:
sys.exit(1)
perm_sco_view = Permission.get_by_name("ScoView")
role_lecteur.add_permission(perm_sco_view)
perm_sco_users = Permission.get_by_name("ScoUsersView")
role_lecteur.add_permission(perm_sco_users)
# Edition billets
perm_billets = Permission.get_by_name("ScoAbsAddBillet")
role_lecteur.add_permission(perm_billets)
@ -92,8 +94,13 @@ def create_users(depts: list[Departement]) -> tuple:
db.session.add(role_lecteur)
# Un role pour juste voir les utilisateurs
role_users_viewer = Role(name="UsersViewer", permissions=Permission.ScoUsersView)
role_users_viewer = Role(
name="UsersViewer", permissions=Permission.ScoUsersView | Permission.ScoView
)
db.session.add(role_users_viewer)
# Role View sur l'API, pour demander un jeton
role_view = Role(name="Viewer", permissions=Permission.ScoView)
db.session.add(role_view)
# Un utilisateur "test" (passwd test) pouvant lire l'API
user_test = User(user_name="test", nom="Doe", prenom="John", dept=dept.acronym)
@ -132,7 +139,7 @@ def create_users(depts: list[Departement]) -> tuple:
for i, u in enumerate(users):
for dept in depts[: i + 1]:
u.add_role(role_users_viewer, dept.acronym)
u.add_role(role_lecteur, None) # necessaire pour avoir le jeton
u.add_role(role_view, None) # necessaire pour avoir le jeton
db.session.commit()
return user_test, other