2021-10-28 00:52:23 +02:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
# -*- mode: python -*-
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
2021-12-21 00:10:51 +01:00
|
|
|
"""Exemple utilisation API ScoDoc 9 avec jeton obtenu par basic authentication
|
2021-10-28 00:52:23 +02:00
|
|
|
|
|
|
|
|
|
|
|
Utilisation: créer les variables d'environnement: (indiquer les valeurs
|
|
|
|
pour le serveur ScoDoc que vous voulez interroger)
|
|
|
|
|
|
|
|
export SCODOC_URL="https://scodoc.xxx.net/"
|
|
|
|
export SCODOC_USER="xxx"
|
|
|
|
export SCODOC_PASSWD="xxx"
|
|
|
|
export CHECK_CERTIFICATE=0 # ou 1 si serveur de production avec certif SSL valide
|
|
|
|
|
|
|
|
(on peut aussi placer ces valeurs dans un fichier .env du répertoire tests/api).
|
|
|
|
|
|
|
|
|
2022-05-03 13:35:17 +02:00
|
|
|
Travail en cours.
|
2021-10-28 00:52:23 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
from dotenv import load_dotenv
|
2022-07-20 22:03:29 +02:00
|
|
|
import json
|
2021-10-28 00:52:23 +02:00
|
|
|
import os
|
|
|
|
import requests
|
|
|
|
import urllib3
|
|
|
|
from pprint import pprint as pp
|
|
|
|
|
|
|
|
# --- Lecture configuration (variables d'env ou .env)
|
2022-05-11 00:59:51 +02:00
|
|
|
try:
|
|
|
|
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
|
|
|
except NameError:
|
|
|
|
BASEDIR = "."
|
|
|
|
|
2021-10-28 00:52:23 +02:00
|
|
|
load_dotenv(os.path.join(BASEDIR, ".env"))
|
2022-05-03 13:35:17 +02:00
|
|
|
CHK_CERT = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
|
2022-07-06 00:05:14 +02:00
|
|
|
SCODOC_URL = os.environ.get("SCODOC_URL") or "http://localhost:5000"
|
2022-05-03 13:35:17 +02:00
|
|
|
API_URL = SCODOC_URL + "/ScoDoc/api"
|
2022-07-22 16:39:21 +02:00
|
|
|
# Admin:
|
2021-10-28 00:52:23 +02:00
|
|
|
SCODOC_USER = os.environ["SCODOC_USER"]
|
2022-05-11 00:59:51 +02:00
|
|
|
SCODOC_PASSWORD = os.environ["SCODOC_PASSWORD"]
|
2022-07-22 16:39:21 +02:00
|
|
|
# Lecteur
|
|
|
|
SCODOC_USER_API_LECTEUR = os.environ["SCODOC_USER_API_LECTEUR"]
|
|
|
|
SCODOC_PASSWORD_API_LECTEUR = os.environ["SCODOC_PASSWORD_API_LECTEUR"]
|
|
|
|
|
2021-10-28 00:52:23 +02:00
|
|
|
print(f"SCODOC_URL={SCODOC_URL}")
|
2022-05-03 13:35:17 +02:00
|
|
|
print(f"API URL={API_URL}")
|
2021-10-28 00:52:23 +02:00
|
|
|
|
|
|
|
# ---
|
2022-05-03 13:35:17 +02:00
|
|
|
if not CHK_CERT:
|
2021-10-28 00:52:23 +02:00
|
|
|
urllib3.disable_warnings()
|
|
|
|
|
|
|
|
|
|
|
|
class ScoError(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2022-07-27 16:03:14 +02:00
|
|
|
def GET(path: str, headers={}, errmsg=None, dept=None):
|
2021-10-28 00:52:23 +02:00
|
|
|
"""Get and returns as JSON"""
|
2022-07-27 16:03:14 +02:00
|
|
|
if dept:
|
|
|
|
url = SCODOC_URL + f"/ScoDoc/{dept}/api" + path
|
|
|
|
else:
|
|
|
|
url = API_URL + path
|
|
|
|
r = requests.get(url, headers=headers or HEADERS, verify=CHK_CERT)
|
2021-10-28 00:52:23 +02:00
|
|
|
if r.status_code != 200:
|
2022-07-25 08:46:24 +02:00
|
|
|
raise ScoError(errmsg or f"""erreur status={r.status_code} !\n{r.text}""")
|
2021-10-28 00:52:23 +02:00
|
|
|
return r.json() # decode la reponse JSON
|
|
|
|
|
|
|
|
|
2022-07-20 16:12:20 +02:00
|
|
|
def POST(path: str, data: dict = {}, headers={}, errmsg=None):
|
2021-10-28 00:52:23 +02:00
|
|
|
"""Post"""
|
2022-07-20 16:12:20 +02:00
|
|
|
r = requests.post(
|
2022-07-20 22:03:29 +02:00
|
|
|
API_URL + path,
|
|
|
|
data=data,
|
|
|
|
headers=headers or HEADERS,
|
|
|
|
verify=CHK_CERT,
|
2022-07-20 16:12:20 +02:00
|
|
|
)
|
2021-10-28 00:52:23 +02:00
|
|
|
if r.status_code != 200:
|
2022-07-25 08:46:24 +02:00
|
|
|
raise ScoError(errmsg or f"erreur status={r.status_code} !\n{r.text}")
|
2022-07-20 22:03:29 +02:00
|
|
|
return r.json() # decode la reponse JSON
|
|
|
|
|
|
|
|
|
|
|
|
def POST_JSON(path: str, data: dict = {}, headers={}, errmsg=None):
|
|
|
|
"""Post"""
|
|
|
|
r = requests.post(
|
|
|
|
API_URL + path,
|
|
|
|
json=data,
|
|
|
|
headers=headers or HEADERS,
|
|
|
|
verify=CHK_CERT,
|
|
|
|
)
|
|
|
|
if r.status_code != 200:
|
2022-07-25 08:46:24 +02:00
|
|
|
raise ScoError(errmsg or f"erreur status={r.status_code} !\n{r.text}")
|
2022-07-20 16:12:20 +02:00
|
|
|
return r.json() # decode la reponse JSON
|
2021-10-28 00:52:23 +02:00
|
|
|
|
|
|
|
|
2022-07-22 16:39:21 +02:00
|
|
|
def GET_TOKEN(user, password):
|
|
|
|
"Obtention du jeton (token)"
|
|
|
|
r = requests.post(API_URL + "/tokens", auth=(user, password))
|
|
|
|
assert r.status_code == 200
|
|
|
|
token = r.json()["token"]
|
|
|
|
return {"Authorization": f"Bearer {token}"}
|
|
|
|
|
|
|
|
|
|
|
|
HEADERS = GET_TOKEN(SCODOC_USER, SCODOC_PASSWORD)
|
|
|
|
HEADERS_USER = GET_TOKEN(SCODOC_USER_API_LECTEUR, SCODOC_PASSWORD_API_LECTEUR)
|
2021-10-28 00:52:23 +02:00
|
|
|
|
2022-05-03 13:35:17 +02:00
|
|
|
r = requests.get(API_URL + "/departements", headers=HEADERS, verify=CHK_CERT)
|
2021-10-28 00:52:23 +02:00
|
|
|
if r.status_code != 200:
|
|
|
|
raise ScoError("erreur de connexion: vérifier adresse et identifiants")
|
|
|
|
|
|
|
|
pp(r.json())
|
|
|
|
|
2022-05-03 13:35:17 +02:00
|
|
|
# Liste de tous les étudiants en cours (de tous les depts)
|
|
|
|
r = requests.get(API_URL + "/etudiants/courant", headers=HEADERS, verify=CHK_CERT)
|
2021-12-21 00:10:51 +01:00
|
|
|
if r.status_code != 200:
|
|
|
|
raise ScoError("erreur de connexion: vérifier adresse et identifiants")
|
|
|
|
|
2022-05-03 13:35:17 +02:00
|
|
|
print(f"{len(r.json())} étudiants courants")
|
|
|
|
|
|
|
|
# Bulletin d'un BUT
|
2022-07-06 00:05:14 +02:00
|
|
|
formsemestre_id = 1063 # A adapter
|
|
|
|
etudid = 16450
|
2022-05-03 13:35:17 +02:00
|
|
|
bul = GET(f"/etudiant/etudid/{etudid}/formsemestre/{formsemestre_id}/bulletin")
|
|
|
|
|
|
|
|
# d'un DUT
|
2022-07-06 00:05:14 +02:00
|
|
|
formsemestre_id = 1062 # A adapter
|
|
|
|
etudid = 16309
|
2022-05-03 13:35:17 +02:00
|
|
|
bul_dut = GET(f"/etudiant/etudid/{etudid}/formsemestre/{formsemestre_id}/bulletin")
|
2021-10-28 00:52:23 +02:00
|
|
|
|
2022-05-11 00:59:51 +02:00
|
|
|
|
|
|
|
# Infos sur un étudiant
|
|
|
|
etudid = 3561
|
|
|
|
code_nip = "11303314"
|
|
|
|
etud = GET(f"/etudiant/etudid/{etudid}")
|
|
|
|
print(etud)
|
|
|
|
|
|
|
|
etud = GET(f"/etudiant/nip/{code_nip}")
|
|
|
|
print(etud)
|
|
|
|
|
|
|
|
sems = GET(f"/etudiant/etudid/{etudid}/formsemestres")
|
|
|
|
print("\n".join([s["titre_num"] for s in sems]))
|
|
|
|
|
|
|
|
sems = GET(f"/etudiant/nip/{code_nip}/formsemestres")
|
|
|
|
print("\n".join([s["titre_num"] for s in sems]))
|
|
|
|
|
2022-05-11 04:14:42 +02:00
|
|
|
# Evaluation
|
|
|
|
evals = GET("/evaluations/1")
|
2022-05-11 00:59:51 +02:00
|
|
|
|
2022-07-20 16:12:20 +02:00
|
|
|
# Partitions d'un BUT
|
|
|
|
formsemestre_id = 1063 # A adapter
|
|
|
|
partitions = GET(f"/formsemestre/{formsemestre_id}/partitions")
|
|
|
|
print(partitions)
|
|
|
|
pid = partitions[1]["id"]
|
|
|
|
partition = GET(f"/partition/{pid}")
|
|
|
|
print(partition)
|
|
|
|
group_id = partition["groups"][0]["id"]
|
|
|
|
etuds = GET(f"/group/{group_id}/etudiants")
|
|
|
|
print(f"{len(etuds)} étudiants")
|
|
|
|
pp(etuds[1])
|
|
|
|
|
|
|
|
etuds_dem = GET(f"/group/{group_id}/etudiants/query?etat=D")
|
|
|
|
print(f"{len(etuds_dem)} étudiants")
|
|
|
|
|
|
|
|
etudid = 16650
|
|
|
|
group_id = 5315
|
|
|
|
POST(f"/group/{group_id}/set_etudiant/{etudid}")
|
|
|
|
|
2022-07-20 22:03:29 +02:00
|
|
|
|
|
|
|
POST_JSON(f"/partition/{pid}/group/create", data={"group_name": "Omega10"})
|
2022-07-20 22:33:41 +02:00
|
|
|
partitions = GET(f"/formsemestre/{formsemestre_id}/partitions")
|
|
|
|
pp(partitions)
|
|
|
|
|
|
|
|
POST_JSON(f"/group/5559/delete")
|
|
|
|
POST_JSON(f"/group/5327/edit", data={"group_name": "TDXXX"})
|
|
|
|
|
2022-07-26 09:00:48 +02:00
|
|
|
# --------- XXX à passer en dans les tests unitaires
|
2022-07-27 16:03:14 +02:00
|
|
|
|
|
|
|
# 0- Prend un étudiant au hasard dans le semestre
|
|
|
|
etud = GET(f"/formsemestre/{formsemestre_id}/etudiants")[10]
|
|
|
|
etudid = etud["id"]
|
|
|
|
|
2022-07-25 08:46:24 +02:00
|
|
|
# 1- Crée une partition, puis la change de nom
|
|
|
|
js = POST_JSON(
|
2022-07-20 22:33:41 +02:00
|
|
|
f"/formsemestre/{formsemestre_id}/partition/create",
|
2022-07-25 08:46:24 +02:00
|
|
|
data={"partition_name": "PART"},
|
2022-07-20 22:33:41 +02:00
|
|
|
)
|
2022-07-25 08:46:24 +02:00
|
|
|
partition_id = js["id"]
|
2022-07-20 22:33:41 +02:00
|
|
|
POST_JSON(
|
2022-07-25 08:46:24 +02:00
|
|
|
f"/partition/{partition_id}/edit",
|
|
|
|
data={"partition_name": "PART1", "show_in_lists": True},
|
2022-07-20 22:33:41 +02:00
|
|
|
)
|
2022-07-20 22:03:29 +02:00
|
|
|
|
2022-07-25 08:46:24 +02:00
|
|
|
# 2- Crée un groupe
|
2022-07-27 16:03:14 +02:00
|
|
|
js = POST_JSON(f"/partition/{partition_id}/group/create", data={"group_name": "G1"})
|
|
|
|
group_1 = js["id"]
|
|
|
|
|
|
|
|
# 3- Crée deux autres groupes
|
|
|
|
js = POST_JSON(f"/partition/{partition_id}/group/create", data={"group_name": "G2"})
|
|
|
|
js = POST_JSON(f"/partition/{partition_id}/group/create", data={"group_name": "G3"})
|
|
|
|
|
|
|
|
# 4- Affecte étudiant au groupe G1
|
|
|
|
POST_JSON(f"/group/{group_1}/set_etudiant/{etudid}")
|
|
|
|
|
|
|
|
# 5- retire du groupe
|
|
|
|
POST_JSON(f"/group/{group_1}/remove_etudiant/{etudid}")
|
2022-07-25 08:46:24 +02:00
|
|
|
|
2022-07-27 16:03:14 +02:00
|
|
|
# 6- affecte au groupe G2
|
|
|
|
partition = GET(f"/partition/{partition_id}")
|
|
|
|
assert len(partition["groups"]) == 3
|
|
|
|
group_2 = [g for g in partition["groups"].values() if g["name"] == "G2"][0]["id"]
|
|
|
|
POST_JSON(f"/group/{group_2}/set_etudiant/{etudid}")
|
2022-07-25 08:46:24 +02:00
|
|
|
|
2022-07-27 16:03:14 +02:00
|
|
|
# 7- Membres du groupe
|
|
|
|
etuds_g2 = GET(f"/group/{group_2}/etudiants")
|
|
|
|
assert len(etuds_g2) == 1
|
|
|
|
assert etuds_g2[0]["id"] == etudid
|
|
|
|
|
|
|
|
# 8- Ordres des groupes
|
|
|
|
group_3 = [g for g in partition["groups"].values() if g["name"] == "G3"][0]["id"]
|
|
|
|
|
|
|
|
POST_JSON(
|
|
|
|
f"/partition/{partition_id}/groups/order",
|
|
|
|
data=[group_2, group_1, group_3],
|
|
|
|
)
|
|
|
|
|
|
|
|
new_groups = [g["id"] for g in GET(f"/partition/{partition_id}")["groups"].values()]
|
|
|
|
assert new_groups == [group_2, group_1, group_3]
|
|
|
|
|
|
|
|
# 9- Suppression
|
2022-07-25 08:46:24 +02:00
|
|
|
POST_JSON(f"/partition/{partition_id}/delete")
|
2022-07-26 09:00:48 +02:00
|
|
|
# ------
|
|
|
|
|
2022-07-27 16:03:14 +02:00
|
|
|
# Tests accès API:
|
|
|
|
"""
|
|
|
|
* En mode API:
|
|
|
|
Avec admin:
|
|
|
|
- GET, POST ci-dessus : OK
|
|
|
|
Avec user ayant ScoView (rôle LecteurAPI)
|
|
|
|
- idem
|
|
|
|
Avec user sans ScoView:
|
|
|
|
- GET et POST: erreur 403
|
|
|
|
* En mode Web:
|
|
|
|
admin: GET
|
|
|
|
user : GET = 403
|
|
|
|
"""
|
2022-07-20 22:03:29 +02:00
|
|
|
|
2022-07-24 22:04:37 +02:00
|
|
|
#
|
|
|
|
POST_JSON(
|
|
|
|
"/partition/2264/groups/order",
|
|
|
|
data=[5563, 5562, 5561, 5560, 5558, 5557, 5316, 5315],
|
|
|
|
)
|
|
|
|
|
|
|
|
POST_JSON(
|
|
|
|
"/formsemestre/1063/partitions/order",
|
|
|
|
data=[2264, 2263, 2265, 2266, 2267, 2372, 2378],
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
GET(f"/partition/2264")
|
|
|
|
|
2022-07-21 08:53:44 +02:00
|
|
|
# Recherche de formsemestres
|
|
|
|
sems = GET(f"/formsemestres/query?etape_apo=V1RT&annee_scolaire=2021")
|
|
|
|
|
2022-07-21 16:46:07 +02:00
|
|
|
# Table récap:
|
|
|
|
pp(GET(f"/formsemestre/1063/resultats")[0])
|
|
|
|
|
|
|
|
pp(GET(f"/formsemestre/880/resultats")[0])
|
2021-10-28 00:52:23 +02:00
|
|
|
|
|
|
|
# # sems est une liste de semestres (dictionnaires)
|
|
|
|
# for sem in sems:
|
|
|
|
# if sem["etat"]:
|
|
|
|
# break
|
|
|
|
|
|
|
|
# if sem["etat"] == "0":
|
|
|
|
# raise ScoError("Aucun semestre non verrouillé !")
|
|
|
|
|
|
|
|
# # Affiche le semestre trouvé:
|
|
|
|
# pp(sem)
|
|
|
|
|
|
|
|
# # ---- Récupère la description de ce semestre:
|
|
|
|
# # semdescr = GET(s, f"Notes/formsemestre_description?formsemestre_id={sem['formsemestre_id']}&with_evals=0&format=json" )
|
|
|
|
|
|
|
|
# # ---- Liste les modules et prend le premier
|
|
|
|
# mods = GET(s, f"/Notes/moduleimpl_list?formsemestre_id={sem['formsemestre_id']}")
|
|
|
|
# print(f"{len(mods)} modules dans le semestre {sem['titre']}")
|
|
|
|
|
|
|
|
# mod = mods[0]
|
|
|
|
|
|
|
|
# # ---- Etudiants inscrits dans ce module
|
|
|
|
# inscrits = GET(
|
|
|
|
# s, f"Notes/do_moduleimpl_inscription_list?moduleimpl_id={mod['moduleimpl_id']}"
|
|
|
|
# )
|
|
|
|
# print(f"{len(inscrits)} inscrits dans ce module")
|
|
|
|
# # prend le premier inscrit, au hasard:
|
|
|
|
# etudid = inscrits[0]["etudid"]
|
|
|
|
|
|
|
|
# # ---- Création d'une evaluation le dernier jour du semestre
|
|
|
|
# jour = sem["date_fin"]
|
|
|
|
# evaluation_id = POST(
|
|
|
|
# s,
|
|
|
|
# "/Notes/do_evaluation_create",
|
|
|
|
# data={
|
|
|
|
# "moduleimpl_id": mod["moduleimpl_id"],
|
|
|
|
# "coefficient": 1,
|
|
|
|
# "jour": jour, # "5/9/2019",
|
|
|
|
# "heure_debut": "9h00",
|
|
|
|
# "heure_fin": "10h00",
|
|
|
|
# "note_max": 20, # notes sur 20
|
|
|
|
# "description": "essai",
|
|
|
|
# },
|
|
|
|
# errmsg="échec création évaluation",
|
|
|
|
# )
|
|
|
|
|
|
|
|
# print(
|
|
|
|
# f"Evaluation créée dans le module {mod['moduleimpl_id']}, evaluation_id={evaluation_id}"
|
|
|
|
# )
|
|
|
|
# print(
|
|
|
|
# f"Pour vérifier, aller sur: {DEPT_URL}/Notes/moduleimpl_status?moduleimpl_id={mod['moduleimpl_id']}",
|
|
|
|
# )
|