forked from ScoDoc/ScoDoc
API scodoc7, exemple/test usage, progres sur l'API scodoc9
This commit is contained in:
parent
db937ca7c5
commit
d2f41b6a21
@ -6,3 +6,4 @@ from flask import Blueprint
|
|||||||
bp = Blueprint("api", __name__)
|
bp = Blueprint("api", __name__)
|
||||||
|
|
||||||
from app.api import sco_api
|
from app.api import sco_api
|
||||||
|
from app.api import tokens
|
||||||
|
@ -33,6 +33,7 @@ token_auth = HTTPTokenAuth()
|
|||||||
|
|
||||||
@basic_auth.verify_password
|
@basic_auth.verify_password
|
||||||
def verify_password(username, password):
|
def verify_password(username, password):
|
||||||
|
# breakpoint()
|
||||||
user = User.query.filter_by(user_name=username).first()
|
user = User.query.filter_by(user_name=username).first()
|
||||||
if user and user.check_password(password):
|
if user and user.check_password(password):
|
||||||
return user
|
return user
|
||||||
@ -51,3 +52,17 @@ def verify_token(token):
|
|||||||
@token_auth.error_handler
|
@token_auth.error_handler
|
||||||
def token_auth_error(status):
|
def token_auth_error(status):
|
||||||
return error_response(status)
|
return error_response(status)
|
||||||
|
|
||||||
|
|
||||||
|
def token_permission_required(permission):
|
||||||
|
def decorator(f):
|
||||||
|
@wraps(f)
|
||||||
|
def decorated_function(*args, **kwargs):
|
||||||
|
scodoc_dept = getattr(g, "scodoc_dept", None)
|
||||||
|
if not current_user.has_permission(permission, scodoc_dept):
|
||||||
|
abort(403)
|
||||||
|
return f(*args, **kwargs)
|
||||||
|
|
||||||
|
return login_required(decorated_function)
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
@ -48,9 +48,9 @@ from app.api.errors import bad_request
|
|||||||
from app import models
|
from app import models
|
||||||
|
|
||||||
|
|
||||||
@bp.route("/ScoDoc/api/list_depts", methods=["GET"])
|
@bp.route("list_depts", methods=["GET"])
|
||||||
@token_auth.login_required
|
@token_auth.login_required
|
||||||
def list_depts():
|
def list_depts():
|
||||||
depts = models.Departement.query.filter_by(visible=True).all()
|
depts = models.Departement.query.filter_by(visible=True).all()
|
||||||
data = {"items": [d.to_dict() for d in depts]}
|
data = [d.to_dict() for d in depts]
|
||||||
return jsonify(data)
|
return jsonify(data)
|
||||||
|
@ -213,6 +213,9 @@ class User(UserMixin, db.Model):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_token(token):
|
def check_token(token):
|
||||||
|
"""Retreive user for given token, chek token's validity
|
||||||
|
and returns the user object.
|
||||||
|
"""
|
||||||
user = User.query.filter_by(token=token).first()
|
user = User.query.filter_by(token=token).first()
|
||||||
if user is None or user.token_expiration < datetime.utcnow():
|
if user is None or user.token_expiration < datetime.utcnow():
|
||||||
return None
|
return None
|
||||||
|
@ -50,6 +50,7 @@ def scodoc(func):
|
|||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def scodoc_function(*args, **kwargs):
|
def scodoc_function(*args, **kwargs):
|
||||||
|
# current_app.logger.info("@scodoc")
|
||||||
# interdit les POST si pas loggué
|
# 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:
|
||||||
current_app.logger.info(
|
current_app.logger.info(
|
||||||
@ -71,6 +72,7 @@ def scodoc(func):
|
|||||||
# current_app.logger.info("setting dept to None")
|
# current_app.logger.info("setting dept to None")
|
||||||
g.scodoc_dept = None
|
g.scodoc_dept = None
|
||||||
g.scodoc_dept_id = -1 # invalide
|
g.scodoc_dept_id = -1 # invalide
|
||||||
|
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return scodoc_function
|
return scodoc_function
|
||||||
@ -100,8 +102,8 @@ def permission_required_compat_scodoc7(permission):
|
|||||||
def decorator(f):
|
def decorator(f):
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
def decorated_function(*args, **kwargs):
|
def decorated_function(*args, **kwargs):
|
||||||
# current_app.logger.warning("PERMISSION; kwargs=%s" % str(kwargs))
|
|
||||||
# cherche les paramètre d'auth:
|
# cherche les paramètre d'auth:
|
||||||
|
# current_app.logger.info("@permission_required_compat_scodoc7")
|
||||||
auth_ok = False
|
auth_ok = False
|
||||||
if request.method == "GET":
|
if request.method == "GET":
|
||||||
user_name = request.args.get("__ac_name")
|
user_name = request.args.get("__ac_name")
|
||||||
@ -116,7 +118,6 @@ def permission_required_compat_scodoc7(permission):
|
|||||||
if u and u.check_password(user_password):
|
if u and u.check_password(user_password):
|
||||||
auth_ok = True
|
auth_ok = True
|
||||||
flask_login.login_user(u)
|
flask_login.login_user(u)
|
||||||
|
|
||||||
# reprend le chemin classique:
|
# reprend le chemin classique:
|
||||||
scodoc_dept = getattr(g, "scodoc_dept", None)
|
scodoc_dept = getattr(g, "scodoc_dept", None)
|
||||||
|
|
||||||
@ -153,6 +154,7 @@ def scodoc7func(func):
|
|||||||
2. or be called directly from Python.
|
2. or be called directly from Python.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# current_app.logger.info("@scodoc7func")
|
||||||
# Détermine si on est appelé via une route ("toplevel")
|
# Détermine si on est appelé via une route ("toplevel")
|
||||||
# ou par un appel de fonction python normal.
|
# ou par un appel de fonction python normal.
|
||||||
top_level = not hasattr(g, "scodoc7_decorated")
|
top_level = not hasattr(g, "scodoc7_decorated")
|
||||||
|
@ -1047,8 +1047,8 @@ def EtatAbsencesDate(group_ids=[], date=None): # list of groups to display
|
|||||||
|
|
||||||
# ----- Gestion des "billets d'absence": signalement par les etudiants eux mêmes (à travers le portail)
|
# ----- Gestion des "billets d'absence": signalement par les etudiants eux mêmes (à travers le portail)
|
||||||
@bp.route("/AddBilletAbsence", methods=["GET", "POST"]) # API ScoDoc 7 compat
|
@bp.route("/AddBilletAbsence", methods=["GET", "POST"]) # API ScoDoc 7 compat
|
||||||
@permission_required_compat_scodoc7(Permission.ScoAbsAddBillet)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoAbsAddBillet)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def AddBilletAbsence(
|
def AddBilletAbsence(
|
||||||
begin,
|
begin,
|
||||||
@ -1238,8 +1238,8 @@ def listeBilletsEtud(etudid=False, format="html"):
|
|||||||
@bp.route(
|
@bp.route(
|
||||||
"/XMLgetBilletsEtud", methods=["GET", "POST"]
|
"/XMLgetBilletsEtud", methods=["GET", "POST"]
|
||||||
) # pour compat anciens clients PHP
|
) # pour compat anciens clients PHP
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def XMLgetBilletsEtud(etudid=False):
|
def XMLgetBilletsEtud(etudid=False):
|
||||||
"""Liste billets pour un etudiant"""
|
"""Liste billets pour un etudiant"""
|
||||||
@ -1464,8 +1464,8 @@ def ProcessBilletAbsenceForm(billet_id):
|
|||||||
|
|
||||||
|
|
||||||
# @bp.route("/essai_api7")
|
# @bp.route("/essai_api7")
|
||||||
# @permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
# @scodoc
|
# @scodoc
|
||||||
|
# @permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
# @scodoc7func
|
# @scodoc7func
|
||||||
# def essai_api7(x="xxx"):
|
# def essai_api7(x="xxx"):
|
||||||
# "un essai"
|
# "un essai"
|
||||||
@ -1474,8 +1474,8 @@ def ProcessBilletAbsenceForm(billet_id):
|
|||||||
|
|
||||||
|
|
||||||
@bp.route("/XMLgetAbsEtud", methods=["GET", "POST"]) # pour compat anciens clients PHP
|
@bp.route("/XMLgetAbsEtud", methods=["GET", "POST"]) # pour compat anciens clients PHP
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def XMLgetAbsEtud(beg_date="", end_date=""):
|
def XMLgetAbsEtud(beg_date="", end_date=""):
|
||||||
"""returns list of absences in date interval"""
|
"""returns list of absences in date interval"""
|
||||||
|
@ -264,10 +264,10 @@ sco_publish(
|
|||||||
|
|
||||||
|
|
||||||
@bp.route(
|
@bp.route(
|
||||||
"formsemestre_bulletinetud", methods=["GET", "POST"]
|
"/formsemestre_bulletinetud", methods=["GET", "POST"]
|
||||||
) # POST pour compat anciens clients PHP (deprecated)
|
) # POST pour compat anciens clients PHP (deprecated)
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def formsemestre_bulletinetud(
|
def formsemestre_bulletinetud(
|
||||||
etudid=None,
|
etudid=None,
|
||||||
@ -642,8 +642,8 @@ sco_publish("/ue_move", sco_edit_formation.ue_move, Permission.ScoChangeFormatio
|
|||||||
@bp.route(
|
@bp.route(
|
||||||
"/formsemestre_list", methods=["GET", "POST"]
|
"/formsemestre_list", methods=["GET", "POST"]
|
||||||
) # pour compat anciens clients PHP
|
) # pour compat anciens clients PHP
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def formsemestre_list(
|
def formsemestre_list(
|
||||||
format="json",
|
format="json",
|
||||||
@ -669,8 +669,8 @@ def formsemestre_list(
|
|||||||
@bp.route(
|
@bp.route(
|
||||||
"/XMLgetFormsemestres", methods=["GET", "POST"]
|
"/XMLgetFormsemestres", methods=["GET", "POST"]
|
||||||
) # pour compat anciens clients PHP
|
) # pour compat anciens clients PHP
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def XMLgetFormsemestres(etape_apo=None, formsemestre_id=None):
|
def XMLgetFormsemestres(etape_apo=None, formsemestre_id=None):
|
||||||
"""List all formsemestres matching etape, XML format
|
"""List all formsemestres matching etape, XML format
|
||||||
|
@ -358,8 +358,8 @@ def search_etud_by_name():
|
|||||||
@bp.route(
|
@bp.route(
|
||||||
"/Notes/XMLgetEtudInfos", methods=["GET", "POST"]
|
"/Notes/XMLgetEtudInfos", methods=["GET", "POST"]
|
||||||
) # pour compat anciens clients PHP
|
) # pour compat anciens clients PHP
|
||||||
@permission_required_compat_scodoc7(Permission.ScoView)
|
|
||||||
@scodoc
|
@scodoc
|
||||||
|
@permission_required_compat_scodoc7(Permission.ScoView)
|
||||||
@scodoc7func
|
@scodoc7func
|
||||||
def etud_info(etudid=None, format="xml"):
|
def etud_info(etudid=None, format="xml"):
|
||||||
"Donne les informations sur un etudiant"
|
"Donne les informations sur un etudiant"
|
||||||
|
@ -1,133 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- mode: python -*-
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""Exemple connexion sur ScoDoc et utilisation de l'API
|
|
||||||
|
|
||||||
- Ouverture session
|
|
||||||
- Liste semestres
|
|
||||||
- Liste modules
|
|
||||||
- Creation d'une évaluation
|
|
||||||
- Saisie d'une note
|
|
||||||
|
|
||||||
Attention: cet exemple est en Python 3 (>= 3.6)
|
|
||||||
"""
|
|
||||||
|
|
||||||
import requests
|
|
||||||
import urllib3
|
|
||||||
import pdb
|
|
||||||
from pprint import pprint as pp
|
|
||||||
from flask import g, url_for
|
|
||||||
|
|
||||||
# A modifier pour votre serveur:
|
|
||||||
CHECK_CERTIFICATE = False # set to True in production
|
|
||||||
BASEURL = "https://scodoc.xxx.net/ScoDoc/RT/Scolarite"
|
|
||||||
USER = "XXX"
|
|
||||||
PASSWORD = "XXX"
|
|
||||||
|
|
||||||
# ---
|
|
||||||
if not CHECK_CERTIFICATE:
|
|
||||||
urllib3.disable_warnings()
|
|
||||||
|
|
||||||
|
|
||||||
class ScoError(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def GET(s, path, errmsg=None):
|
|
||||||
"""Get and returns as JSON"""
|
|
||||||
r = s.get(BASEURL + "/" + path, verify=CHECK_CERTIFICATE)
|
|
||||||
if r.status_code != 200:
|
|
||||||
raise ScoError(errmsg or "erreur !")
|
|
||||||
return r.json() # decode la reponse JSON
|
|
||||||
|
|
||||||
|
|
||||||
def POST(s, path, data, errmsg=None):
|
|
||||||
"""Post"""
|
|
||||||
r = s.post(BASEURL + "/" + path, data=data, verify=CHECK_CERTIFICATE)
|
|
||||||
if r.status_code != 200:
|
|
||||||
raise ScoError(errmsg or "erreur !")
|
|
||||||
return r.text
|
|
||||||
|
|
||||||
|
|
||||||
# --- Ouverture session (login)
|
|
||||||
s = requests.Session()
|
|
||||||
s.post(
|
|
||||||
"https://deb11.viennet.net/api/auth/login",
|
|
||||||
data={"user_name": USER, "password": PASSWORD},
|
|
||||||
)
|
|
||||||
r = s.get(BASEURL, auth=(USER, PASSWORD), verify=CHECK_CERTIFICATE)
|
|
||||||
if r.status_code != 200:
|
|
||||||
raise ScoError("erreur de connection: vérifier adresse et identifiants")
|
|
||||||
|
|
||||||
# --- Recupere la liste de tous les semestres:
|
|
||||||
sems = GET(s, "Notes/formsemestre_list?format=json", "Aucun semestre !")
|
|
||||||
|
|
||||||
# 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(
|
|
||||||
"Pour vérifier, aller sur: ",
|
|
||||||
url_for(
|
|
||||||
"notes.moduleimpl_status",
|
|
||||||
scodoc_dept="DEPT",
|
|
||||||
moduleimpl_id=mod["moduleimpl_id"],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# ---- Saisie d'une note
|
|
||||||
junk = POST(
|
|
||||||
s,
|
|
||||||
"/Notes/save_note",
|
|
||||||
data={
|
|
||||||
"etudid": etudid,
|
|
||||||
"evaluation_id": evaluation_id,
|
|
||||||
"value": 16.66, # la note !
|
|
||||||
"comment": "test API",
|
|
||||||
},
|
|
||||||
)
|
|
149
tests/api/exemple-api-basic.py
Normal file
149
tests/api/exemple-api-basic.py
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- mode: python -*-
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Exemple utilisation API ScoDoc 9 avec jeton obtenu par basic athentication
|
||||||
|
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
|
||||||
|
Travail en cours, un seul point d'API (list_depts).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
import pdb
|
||||||
|
import requests
|
||||||
|
import urllib3
|
||||||
|
from pprint import pprint as pp
|
||||||
|
|
||||||
|
# --- Lecture configuration (variables d'env ou .env)
|
||||||
|
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
load_dotenv(os.path.join(BASEDIR, ".env"))
|
||||||
|
CHECK_CERTIFICATE = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
|
||||||
|
SCODOC_URL = os.environ["SCODOC_URL"]
|
||||||
|
SCODOC_DEPT = os.environ["SCODOC_DEPT"]
|
||||||
|
DEPT_URL = SCODOC_URL + "/ScoDoc/" + SCODOC_DEPT + "/Scolarite/"
|
||||||
|
SCODOC_USER = os.environ["SCODOC_USER"]
|
||||||
|
SCODOC_PASSWORD = os.environ["SCODOC_PASSWD"]
|
||||||
|
print(f"SCODOC_URL={SCODOC_URL}")
|
||||||
|
|
||||||
|
# ---
|
||||||
|
if not CHECK_CERTIFICATE:
|
||||||
|
urllib3.disable_warnings()
|
||||||
|
|
||||||
|
|
||||||
|
class ScoError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def GET(path: str, headers={}, errmsg=None):
|
||||||
|
"""Get and returns as JSON"""
|
||||||
|
r = requests.get(
|
||||||
|
DEPT_URL + "/" + path, headers=headers or HEADERS, verify=CHECK_CERTIFICATE
|
||||||
|
)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise ScoError(errmsg or "erreur !")
|
||||||
|
return r.json() # decode la reponse JSON
|
||||||
|
|
||||||
|
|
||||||
|
def POST(s, path: str, data: dict, errmsg=None):
|
||||||
|
"""Post"""
|
||||||
|
r = s.post(DEPT_URL + "/" + path, data=data, verify=CHECK_CERTIFICATE)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise ScoError(errmsg or "erreur !")
|
||||||
|
return r.text
|
||||||
|
|
||||||
|
|
||||||
|
# --- Obtention du jeton (token)
|
||||||
|
r = requests.post(
|
||||||
|
SCODOC_URL + "/ScoDoc/api/tokens", auth=(SCODOC_USER, SCODOC_PASSWORD)
|
||||||
|
)
|
||||||
|
assert r.status_code == 200
|
||||||
|
token = r.json()["token"]
|
||||||
|
HEADERS = {"Authorization": f"Bearer {token}"}
|
||||||
|
|
||||||
|
r = requests.get(
|
||||||
|
SCODOC_URL + "/ScoDoc/api/list_depts", headers=HEADERS, verify=CHECK_CERTIFICATE
|
||||||
|
)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise ScoError("erreur de connexion: vérifier adresse et identifiants")
|
||||||
|
|
||||||
|
pp(r.json())
|
||||||
|
|
||||||
|
|
||||||
|
# # --- Recupere la liste de tous les semestres:
|
||||||
|
# sems = GET(s, "Notes/formsemestre_list?format=json", "Aucun semestre !")
|
||||||
|
|
||||||
|
# # 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']}",
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # ---- Saisie d'une note
|
||||||
|
# junk = POST(
|
||||||
|
# s,
|
||||||
|
# "/Notes/save_note",
|
||||||
|
# data={
|
||||||
|
# "etudid": etudid,
|
||||||
|
# "evaluation_id": evaluation_id,
|
||||||
|
# "value": 16.66, # la note !
|
||||||
|
# "comment": "test API",
|
||||||
|
# },
|
||||||
|
# )
|
144
tests/api/exemple-api-scodoc7.py
Normal file
144
tests/api/exemple-api-scodoc7.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- mode: python -*-
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Exemple connexion sur ScoDoc 9 et utilisation de l'ancienne API ScoDoc 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"
|
||||||
|
et ne sera plus supporté à partir de juillet 2022.
|
||||||
|
|
||||||
|
Ce script va tester:
|
||||||
|
- Liste semestres
|
||||||
|
- Liste modules
|
||||||
|
- Creation d'une évaluation
|
||||||
|
- Saisie d'une note
|
||||||
|
|
||||||
|
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).
|
||||||
|
"""
|
||||||
|
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
import os
|
||||||
|
import pdb
|
||||||
|
import requests
|
||||||
|
import urllib3
|
||||||
|
from pprint import pprint as pp
|
||||||
|
|
||||||
|
# --- Lecture configuration (variables d'env ou .env)
|
||||||
|
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
load_dotenv(os.path.join(BASEDIR, ".env"))
|
||||||
|
CHECK_CERTIFICATE = bool(int(os.environ.get("CHECK_CERTIFICATE", False)))
|
||||||
|
SCODOC_URL = os.environ["SCODOC_URL"]
|
||||||
|
SCODOC_DEPT = os.environ["SCODOC_DEPT"]
|
||||||
|
DEPT_URL = SCODOC_URL + "/ScoDoc/" + SCODOC_DEPT + "/Scolarite"
|
||||||
|
SCODOC_USER = os.environ["SCODOC_USER"]
|
||||||
|
SCODOC_PASSWORD = os.environ["SCODOC_PASSWD"]
|
||||||
|
print(f"SCODOC_URL={SCODOC_URL}")
|
||||||
|
|
||||||
|
# ---
|
||||||
|
if not CHECK_CERTIFICATE:
|
||||||
|
urllib3.disable_warnings()
|
||||||
|
|
||||||
|
|
||||||
|
class ScoError(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def GET(path: str, params=None, errmsg=None):
|
||||||
|
"""Get and returns as JSON"""
|
||||||
|
# ajoute auth
|
||||||
|
params["__ac_name"] = SCODOC_USER
|
||||||
|
params["__ac_password"] = SCODOC_PASSWORD
|
||||||
|
r = requests.get(DEPT_URL + "/" + path, params=params, verify=CHECK_CERTIFICATE)
|
||||||
|
if r.status_code != 200:
|
||||||
|
raise ScoError(errmsg or "erreur !")
|
||||||
|
return r.json() # decode la reponse JSON
|
||||||
|
|
||||||
|
|
||||||
|
def POST(path: str, data: dict, errmsg=None):
|
||||||
|
"""Post"""
|
||||||
|
data["__ac_name"] = SCODOC_USER
|
||||||
|
data["__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
|
||||||
|
|
||||||
|
|
||||||
|
# ---
|
||||||
|
# pas besoin d'ouvrir une session, on y va directement:
|
||||||
|
|
||||||
|
# --- Recupere la liste de tous les semestres:
|
||||||
|
sems = GET("Notes/formsemestre_list", params={"format": "json"})
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# Les fonctions ci-dessous ne fonctionne plus en ScoDoc 9
|
||||||
|
# Voir https://scodoc.org/git/viennet/ScoDoc/issues/149
|
||||||
|
|
||||||
|
# # ---- Liste les modules et prend le premier
|
||||||
|
# mods = GET("/Notes/moduleimpl_list", params={"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(
|
||||||
|
# "Notes/do_moduleimpl_inscription_list",
|
||||||
|
# params={"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(
|
||||||
|
# "/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']}",
|
||||||
|
# )
|
||||||
|
|
||||||
|
# # ---- Saisie d'une note
|
||||||
|
# junk = POST(
|
||||||
|
# "/Notes/save_note",
|
||||||
|
# data={
|
||||||
|
# "etudid": etudid,
|
||||||
|
# "evaluation_id": evaluation_id,
|
||||||
|
# "value": 16.66, # la note !
|
||||||
|
# "comment": "test API",
|
||||||
|
# },
|
||||||
|
# )
|
Loading…
Reference in New Issue
Block a user