API ScoDoc 7: autorise POSTs, ajoute groups_view, script exemple/test

This commit is contained in:
Emmanuel Viennet 2021-11-01 16:59:56 +01:00
parent 01a84f3b12
commit 7589d4cc34
4 changed files with 109 additions and 21 deletions

View File

@ -50,9 +50,15 @@ def scodoc(func):
@wraps(func)
def scodoc_function(*args, **kwargs):
# current_app.logger.info("@scodoc")
# print("@scodoc")
# interdit les POST si pas loggué
if request.method == "POST" and not current_user.is_authenticated:
if (
request.method == "POST"
and not current_user.is_authenticated
and not request.form.get(
"__ac_password"
) # exception pour compat API ScoDoc7
):
current_app.logger.info(
"POST by non authenticated user (request.form=%s)",
str(request.form)[:2048],
@ -103,7 +109,7 @@ def permission_required_compat_scodoc7(permission):
@wraps(f)
def decorated_function(*args, **kwargs):
# cherche les paramètre d'auth:
# current_app.logger.info("@permission_required_compat_scodoc7")
# print("@permission_required_compat_scodoc7")
auth_ok = False
if request.method == "GET":
user_name = request.args.get("__ac_name")
@ -154,7 +160,7 @@ def scodoc7func(func):
2. or be called directly from Python.
"""
# current_app.logger.info("@scodoc7func")
# print("@scodoc7func")
# Détermine si on est appelé via une route ("toplevel")
# ou par un appel de fonction python normal.
top_level = not hasattr(g, "scodoc7_decorated")

View File

@ -1058,7 +1058,8 @@ def AddBilletAbsence(
code_nip=None,
code_ine=None,
justified=True,
xml_reply=True,
format="json",
xml_reply=True, # deprecated
):
"""Mémorise un "billet"
begin et end sont au format ISO (eg "1999-01-08 04:05:06")
@ -1082,6 +1083,7 @@ def AddBilletAbsence(
raise ValueError("invalid dates")
#
justified = bool(justified)
xml_reply = bool(xml_reply)
#
cnx = ndb.GetDBConnexion()
billet_id = sco_abs.billet_absence_create(
@ -1095,14 +1097,14 @@ def AddBilletAbsence(
"justified": justified,
},
)
if xml_reply:
# Renvoie le nouveau billet en XML
billets = sco_abs.billet_absence_list(cnx, {"billet_id": billet_id})
tab = _tableBillets(billets, etud=etud)
log("AddBilletAbsence: new billet_id=%s (%gs)" % (billet_id, time.time() - t0))
return tab.make_page(format="xml")
else:
return billet_id
if xml_reply: # backward compat
format = "xml"
# Renvoie le nouveau billet au format demandé
billets = sco_abs.billet_absence_list(cnx, {"billet_id": billet_id})
tab = _tableBillets(billets, etud=etud)
log("AddBilletAbsence: new billet_id=%s (%gs)" % (billet_id, time.time() - t0))
return tab.make_page(format=format)
@bp.route("/AddBilletAbsenceForm", methods=["GET", "POST"])

View File

@ -302,7 +302,34 @@ sco_publish(
methods=["GET", "POST"],
)
sco_publish("/groups_view", sco_groups_view.groups_view, Permission.ScoView)
@bp.route("/groups_view")
@scodoc
@permission_required_compat_scodoc7(Permission.ScoView)
@scodoc7func
def groups_view(
group_ids=(),
format="html",
# Options pour listes:
with_codes=0,
etat=None,
with_paiement=0, # si vrai, ajoute colonnes infos paiement droits et finalisation inscription (lent car interrogation portail)
with_archives=0, # ajoute colonne avec noms fichiers archivés
with_annotations=0,
formsemestre_id=None,
):
return sco_groups_view.groups_view(
group_ids=(),
format=format,
# Options pour listes:
with_codes=with_codes,
etat=etat,
with_paiement=with_paiement, # si vrai, ajoute colonnes infos paiement droits et finalisation inscription (lent car interrogation portail)
with_archives=with_archives, # ajoute colonne avec noms fichiers archivés
with_annotations=with_annotations,
formsemestre_id=formsemestre_id,
)
sco_publish(
"/export_groups_as_moodle_csv",

View File

@ -6,7 +6,7 @@
à la mode "PHP": les gens passaient directement __ac_name et __ac_password
dans chaque requête, en POST ou en GET.
Cela n'a jamais été documenté mais était implitement supporté. C'est "deprecated"
Cela n'a jamais été documenté mais était implicitement supporté. C'est "deprecated"
et ne sera plus supporté à partir de juillet 2022.
Ce script va tester:
@ -27,6 +27,7 @@ export CHECK_CERTIFICATE=0 # ou 1 si serveur de production avec certif SSL valid
"""
from dotenv import load_dotenv
import json
import os
import pdb
import requests
@ -66,12 +67,10 @@ def GET(path: str, params=None, errmsg=None):
def POST(path: str, data: dict, errmsg=None):
"""Post"""
data["__ac_name"] = SCODOC_USER
data["__ac_password"] = SCODOC_PASSWORD
data["__ac_name"] = data.get("__ac_name", SCODOC_USER)
data["__ac_password"] = data.get("__ac_password", SCODOC_PASSWORD)
r = requests.post(DEPT_URL + "/" + path, data=data, verify=CHECK_CERTIFICATE)
if r.status_code != 200:
raise ScoError(errmsg or "erreur !")
return r.text
return r
# ---
@ -91,7 +90,61 @@ if sem["etat"] == "0":
# Affiche le semestre trouvé:
pp(sem)
# Les fonctions ci-dessous ne fonctionne plus en ScoDoc 9
# Liste des étudiants dans le 1er semestre non verrouillé:
group_list = GET(
"groups_view",
params={
"formsemestre_id": sem["formsemestre_id"],
"with_codes": 1,
"format": "json",
},
)
if not group_list:
# config inadaptée pour les tests...
raise ScoError("aucun étudiant inscrit dans le semestre")
etud = group_list[0] # le premier étudiant inscrit ici
# test un POST
r = POST(
"Absences/AddBilletAbsence",
{
"begin": "2021-10-25",
"end": "2021-10-26",
"description": "test API scodoc7",
"etudid": etud["etudid"],
},
)
assert r.status_code == 200
assert r.text.startswith('<?xml version="1.0" encoding="utf-8"?>')
assert "billet_id" in r.text
# Essai avec un compte invalide
r_invalid = POST(
"Absences/AddBilletAbsence",
{
"__ac_name": "xxx",
"begin": "2021-10-25",
"end": "2021-10-26",
"description": "test API scodoc7",
"etudid": etud["etudid"],
},
)
assert r_invalid.status_code == 403 # compte invalide => not authorized
# AddBilletAbsence en json
r = POST(
"Absences/AddBilletAbsence",
{
"begin": "2021-10-25",
"end": "2021-10-26",
"description": "test API scodoc7",
"etudid": etud["etudid"],
"xml_reply": 0,
},
)
assert r.status_code == 200
assert isinstance(json.loads(r.text)[0]["billet_id"], int)
# Les fonctions ci-dessous ne fonctionnent plus en ScoDoc 9
# Voir https://scodoc.org/git/viennet/ScoDoc/issues/149
# # ---- Liste les modules et prend le premier