Traitement des erreurs API (templates rudimentaires)

This commit is contained in:
Ilona 2025-01-03 17:32:03 +01:00
parent 42570cf435
commit d733e68683
7 changed files with 79 additions and 20 deletions

@ -35,7 +35,9 @@ Côté ScoDoc, créer un rôle et un utilisateur dédiés:
flask create-role AutoSco
flask edit-role AutoSco -a ScoView
flask user-create autosco AutoSco @all
flask user-edit autosco --allow-scodoc-login
flask user-password autosco
```
Configurer les paramètres d'accès dans AutoSco: éditer le fichier

@ -1,6 +1,10 @@
from flask import current_app, g, request
import sys
import time
from flask import current_app, g, render_template, request
from flask import Flask
from scodoc.api import APIError, ScoDocAuthError
from config import DevConfig
@ -18,6 +22,30 @@ class ReverseProxied:
environ["wsgi.url_scheme"] = scheme # ou forcer à https ici ?
return self.app(environ, start_response)
# --------- Logging
def log(msg: str):
"""log a message.
If Flask app, use configured logger, else stderr.
"""
if current_app and not current_app.config["DEBUG"]:
current_app.logger.info(msg)
else:
sys.stdout.flush()
sys.stderr.write(
f"""[{time.strftime("%a %b %d %H:%M:%S %Y")}] scodoc: {msg}\n"""
)
sys.stderr.flush()
def handle_sco_api_error(exc):
"page d'erreur avec message"
log("Error: handle_sco_api_error")
return render_template("errors/sco_api_error.j2", exc=exc), 404
def handle_sco_auth_error(exc):
"page d'erreur avec message"
log("Error: handle_sco_auth_error")
return render_template("errors/sco_auth_error.j2", exc=exc), 404
def create_app(config_class=DevConfig):
app = Flask(__name__, static_url_path="/AutoSco/static", static_folder="static")
@ -27,4 +55,8 @@ def create_app(config_class=DevConfig):
from app.views import bp
app.register_blueprint(bp)
app.register_error_handler(APIError, handle_sco_api_error)
app.register_error_handler(ScoDocAuthError, handle_sco_auth_error)
return app

@ -0,0 +1,13 @@
{% extends 'base.j2' %}
{% block content %}
<div>
<h1>Erreur API</h1>
<div>ScoDoc a renvoyé une erreur {{exc.status_code}}</div>
<div>Message: {{exc.payload["message"]}}</div>
<div>Requête: {{exc.message}}</div>
<div>Si le problème persiste, veuillez contacter le support technique.</div>
</div>
{% endblock %}

@ -0,0 +1,11 @@
{% extends 'base.j2' %}
{% block content %}
<div>
<h1>Erreur d'authentification</h1>
<div>AutoSco ne parvient pas à se connecter à ScoDoc</div>
<div>Si le problème persiste, veuillez contacter le support technique.</div>
</div>
{% endblock %}

@ -45,7 +45,6 @@ def make_shell_context():
"scu": scu,
}
# Start using:
# flask run -p 5001 --host 0.0.0.0 --debug
if __name__ == "__main__":
port = os.environ.get("PORT", 5001)
app.run(debug=True, port=port)

@ -40,7 +40,7 @@ class Config:
SCODOC_CHECK_CERTIFICATE = os.environ.get("SCODOC_CHECK_CERTIFICATE", True)
API_TIMEOUT = 120 # 2 minutes
API_URL = SCODOC_URL + "/ScoDoc/api"
SCODOC_DEPT_ACRONYM = "ESPL"
SCODOC_DEPT_ACRONYM = os.environ.get("SCODOC_DEPT_ACRONYM", "ESPL")
def __getitem__(self, k) -> str | int | None:
return getattr(self, k)

@ -7,20 +7,8 @@ from flask import current_app
import config
def get_auth_headers(user: str, password: str, conf: config.Config) -> dict:
"Demande de jeton, dict à utiliser dans les en-têtes de requêtes http"
ans = requests.post(
conf["API_URL"] + "/tokens",
auth=(user, password),
timeout=conf["API_TIMEOUT"],
)
if ans.status_code != 200:
raise APIError(f"Echec demande jeton par {user}", status_code=ans.status_code)
token = ans.json()["token"]
return {"Authorization": f"Bearer {token}"}
class APIError(Exception):
"Error using ScoDoc API"
def __init__(self, message: str = "", payload=None, status_code=None):
self.message = message
self.payload = payload or {}
@ -29,6 +17,20 @@ class APIError(Exception):
def __str__(self):
return f"APIError: {self.message} payload={self.payload} status_code={self.status_code}"
class ScoDocAuthError(APIError):
"Error getting ScoDoc token"
def get_auth_headers(user: str, password: str, conf: config.Config) -> dict:
"Demande de jeton, dict à utiliser dans les en-têtes de requêtes http"
ans = requests.post(
conf["API_URL"] + "/tokens",
auth=(user, password),
timeout=conf["API_TIMEOUT"],
)
if ans.status_code != 200:
raise ScoDocAuthError(f"Echec demande jeton par {user}", status_code=ans.status_code)
token = ans.json()["token"]
return {"Authorization": f"Bearer {token}"}
class APIAccessor:
"Gestion bas niveau des accès à l'API ScoDoc"
@ -64,9 +66,9 @@ class APIAccessor:
print("url", url)
print("reply", reply.text)
try:
payload = r.json()
payload = reply.json()
except requests.exceptions.JSONDecodeError:
payload = r.text
payload = reply.text
raise APIError(
errmsg or f"""erreur get {url} !""",
payload,