From a761a628bd93a700d714ef351db8ee6a7751c768 Mon Sep 17 00:00:00 2001 From: Jean-Marie PLACE Date: Fri, 19 Aug 2022 12:28:07 +0200 Subject: [PATCH] ajouts logos + extension make_sample --- app/api/logos.py | 56 +++++++++++-------- tests/api/make_samples.py | 43 +++++++++----- tests/api/samples.csv | 20 ++++++- tests/api/setup_test_api.py | 21 ++++++- .../fakedatabase/create_test_api_database.py | 16 ++++++ 5 files changed, 118 insertions(+), 38 deletions(-) diff --git a/app/api/logos.py b/app/api/logos.py index ef3a7f973..49c0619c6 100644 --- a/app/api/logos.py +++ b/app/api/logos.py @@ -46,23 +46,16 @@ from app.scodoc.sco_permissions import Permission @bp.route("/logos") @scodoc -@permission_required(Permission.ScoView) +@permission_required(Permission.ScoSuperAdmin) def api_get_glob_logos(): - if not g.current_user.has_permission(Permission.ScoSuperAdmin, None): - return json_error(403, message="accès interdit") - required_format = requested_format() # json only - if required_format is None: - return json_error(400, "Illegal format") logos = list_logos()[None] return jsonify(list(logos.keys())) -@bp.route("/logos/") +@bp.route("/logo/") @scodoc -@permission_required(Permission.ScoView) +@permission_required(Permission.ScoSuperAdmin) def api_get_glob_logo(logoname): - if not g.current_user.has_permission(Permission.ScoSuperAdmin, None): - return json_error(403, message="accès interdit") logo = find_logo(logoname=logoname) if logo is None: return json_error(404, message="logo not found") @@ -74,25 +67,27 @@ def api_get_glob_logo(logoname): ) -@bp.route("/departements//logos") -@scodoc -@permission_required(Permission.ScoView) -def api_get_local_logos(departement): - dept_id = Departement.from_acronym(departement).id - if not g.current_user.has_permission(Permission.ScoChangePreferences, departement): - return json_error(403, message="accès interdit") +def core_get_logos(dept_id): logos = list_logos().get(dept_id, dict()) return jsonify(list(logos.keys())) -@bp.route("/departements//logos/") +@bp.route("/departement//logos") @scodoc -@permission_required(Permission.ScoView) -def api_get_local_logo(departement, logoname): - # format = requested_format("jpg", ['png', 'jpg']) XXX ? +@permission_required(Permission.ScoSuperAdmin) +def api_get_local_logos_by_acronym(departement): dept_id = Departement.from_acronym(departement).id - if not g.current_user.has_permission(Permission.ScoChangePreferences, departement): - return json_error(403, message="accès interdit") + return core_get_logos(dept_id) + + +@bp.route("/departement/id//logos") +@scodoc +@permission_required(Permission.ScoSuperAdmin) +def api_get_local_logos_by_id(dept_id): + return core_get_logos(dept_id) + + +def core_get_logo(dept_id, logoname): logo = find_logo(logoname=logoname, dept_id=dept_id) if logo is None: return json_error(404, message="logo not found") @@ -102,3 +97,18 @@ def api_get_local_logo(departement, logoname): mimetype=f"image/{logo.suffix}", last_modified=datetime.now(), ) + + +@bp.route("/departement//logo/") +@scodoc +@permission_required(Permission.ScoSuperAdmin) +def api_get_local_logo_dept_by_acronym(departement, logoname): + dept_id = Departement.from_acronym(departement).id + return core_get_logo(dept_id, logoname) + + +@bp.route("/departement/id//logo/") +@scodoc +@permission_required(Permission.ScoSuperAdmin) +def api_get_local_logo_dept_by_id(dept_id, logoname): + return core_get_logo(dept_id, logoname) diff --git a/tests/api/make_samples.py b/tests/api/make_samples.py index fbb198283..d712bd5e0 100644 --- a/tests/api/make_samples.py +++ b/tests/api/make_samples.py @@ -6,8 +6,9 @@ Usage: cd /opt/scodoc/tests/api - python make_samples.py + python make_samples.py [entry_names] +si entry_names est spécifié, la génération est restreints aux exemples cités. expl: `python make_samples departements departement-formsemestres` doit être exécutée immédiatement apres une initialisation de la base pour test API! (car dépendant des identifiants générés lors de la création des objets) cd /opt/scodoc/tests/api tools/create_database.sh --drop SCODOC_TEST_API && flask db upgrade &&flask sco-db-init --erase && flask init-test-database @@ -41,6 +42,7 @@ TODO: ajouter un argument au script permettant de ne générer qu'un seul fichie """ import os import shutil +import sys from collections import defaultdict from pprint import pprint as pp from pprint import pformat as pf @@ -69,6 +71,7 @@ class Sample: self.url = url self.method = method self.result = None + self.output = "json" if permission == "ScoView": HEADERS = get_auth_headers("test", "test") elif permission == "ScoSuperAdmin": @@ -87,16 +90,16 @@ class Sample: self.result = POST_JSON(self.url, json.loads(self.content), HEADERS) elif self.method[0] != "#": raise Exception(f"Bad method : {self.method}") - else: # method begin with # => comment - print(" pass") self.shorten() file = open(f"sample_TEST.json.md", "tw") self.dump(file) file.close() - def _shorten(self, item): + def _shorten( + self, item + ): # abrege les longues listes (limite à 2 éléments et affiche "... etc. à la place" if isinstance(item, list): - return [self._shorten(child) for child in item[:2]] + return [self._shorten(child) for child in item[:2]] + ["... etc."] return item def shorten(self): @@ -122,14 +125,24 @@ class Sample: class Samples: - def __init__(self): + def __init__(self, entry_names): + """Entry_names: la liste des entrées à reconstruire. + si None, la totalité des lignes de samples.csv est prise en compte + """ self.entries = defaultdict(lambda: set()) + self.entry_names = entry_names def add_sample(self, entry, url, method="GET", permission="ScoView", content=None): - show_content = "" if content == "" else f": '{content}'" - print(f"{entry:50} {method:5} {url:50} {show_content}") - sample = Sample(url, method, permission, content) - self.entries[entry].add(sample) + if self.entry_names is None or entry in self.entry_names: + if method[0] == "#": + detail = "**ignored**" + elif content == "": + detail = "" + else: + detail = f": {content}" + print(f"{entry:50} {method:5} {url:50} {detail}") + sample = Sample(url, method, permission, content) + self.entries[entry].add(sample) def pp(self): for entry, samples in self.entries.items(): @@ -147,6 +160,10 @@ class Samples: def make_samples(): + if len(sys.argv) == 1: + entry_names = None + else: + entry_names = sys.argv[1:] if os.path.exists(DATA_DIR): if not os.path.isdir(DATA_DIR): raise f"{DATA_DIR} existe déjà et n'est pas un répertoire" @@ -157,9 +174,9 @@ def make_samples(): else: os.mkdir("/tmp/samples") - samples = Samples() - # samples.pp() - with open("samples.csv") as f: + samples = Samples(entry_names) + samples_file = os.path.dirname(__file__) + "/samples.csv" + with open(samples_file) as f: L = [x[:-1].split("\t") for x in f] for line in L[1:]: entry_name = line[0] diff --git a/tests/api/samples.csv b/tests/api/samples.csv index 341bda1e8..2a3880530 100644 --- a/tests/api/samples.csv +++ b/tests/api/samples.csv @@ -26,6 +26,7 @@ etudiant_formsemestres /etudiant/nip/11/formsemestres GET etudiant-formsemestre-bulletin /etudiant/etudid/11/formsemestre/1/bulletin GET etudiant-formsemestre-bulletin /etudiant/ine/INE11/formsemestre/1/bulletin GET etudiant-formsemestre-bulletin /etudiant/nip/11/formsemestre/1/bulletin GET +etudiant-formsemestre-bulletin /etudiant/nip/11/formsemestre/1/bulletin/short/pdf GET etudiant-formsemestre-groups /etudiant/etudid/11/formsemestre/1/groups GET formations /formations GET formations_ids /formations_ids GET @@ -73,5 +74,22 @@ role-create /role/create/customRole ScoSuperAdmin POST {"permissions": ["ScoView role-remove_permission /role/customRole/remove_permission/ScoUsersView ScoSuperAdmin POST role-add_permission /role/customRole/add_permission/ScoUsersView ScoSuperAdmin POST role-edit /role/customRole/edit ScoSuperAdmin POST { "name" : "LaveurDeVitres", "permissions" : [ "ScoView", "APIView" ] } -role-edit /role/customRole/edit ScoSuperAdmin POST { "name" : "LaveurDeVitres", "permissions" : [ "ScoView", "APIView" ] } role-delete /role/customRole/delete ScoSuperAdmin POST +logos /logos ScoSuperAdmin GET +logo /logo/demo ScoSuperAdmin GET +departement-logos /departement/TAPI/logos ScoSuperAdmin GET +departement-logos /departement/id/1/logos ScoSuperAdmin GET +departement-logo /departement/TAPI/logo/demo ScoSuperAdmin GET +departement-logo /departement/id/1/logo/demo ScoSuperAdmin GET +test-pdf /etudiant/nip/11/formsemestre/1/bulletin/pdf GET +test-pdf /etudiant/nip/11/formsemestre/1/bulletin/pdf GET +test-pdf /etudiant/etudid/11/formsemestre/1/bulletin/short/pdf GET +test-pdf /etudiant/ine/INE11/formsemestre/1/bulletin/short/pdf GET +test-pdf /etudiant/nip/11/formsemestre/1/bulletin/short/pdf GET +test-pdf /etudiant/etudid/11/formsemestre/1/bulletin/pdf GET +test-pdf /etudiant/etudid/11/formsemestre/1/bulletin/short GET +test-pdf /etudiant/ine/INE11/formsemestre/1/bulletin/short GET +test-pdf /etudiant/nip/11/formsemestre/1/bulletin/short GET +test-pdf /etudiant/etudid/11/formsemestre/1/bulletin GET +test-pdf /etudiant/ine/INE11/formsemestre/1/bulletin GET +test-pdf /etudiant/nip/11/formsemestre/1/bulletin GET diff --git a/tests/api/setup_test_api.py b/tests/api/setup_test_api.py index fb7517ce8..95e1a854d 100644 --- a/tests/api/setup_test_api.py +++ b/tests/api/setup_test_api.py @@ -65,7 +65,9 @@ def api_admin_headers() -> dict: def GET(path: str, headers: dict = None, errmsg=None, dept=None): - """Get and returns as JSON""" + """Get and returns as JSON + Exception for non json result (image or pdf): return Content-Disposition string (inline or attachment) + """ if dept: url = SCODOC_URL + f"/ScoDoc/{dept}/api" + path else: @@ -73,6 +75,23 @@ def GET(path: str, headers: dict = None, errmsg=None, dept=None): r = requests.get(url, headers=headers or {}, verify=CHECK_CERTIFICATE) if r.status_code != 200: raise APIError(errmsg or f"""erreur status={r.status_code} !""", r.json()) + + if r.headers.get("Content-Type", None) == "application/json": + return r.json() # decode la reponse JSON + elif r.headers.get("Content-Type", None) in [ + "image/jpg", + "image/png", + "application/pdf", + ]: + retval = { + "Content-Type": r.headers.get("Content-Type", None), + "Content-Disposition": r.headers.get("Content-Disposition", None), + } + return retval + else: + raise APIError( + "Unknown returned content {r.headers.get('Content-Type', None} !\n" + ) return r.json() # decode la reponse JSON diff --git a/tools/fakedatabase/create_test_api_database.py b/tools/fakedatabase/create_test_api_database.py index 03e4f7bf9..eb91e06e1 100644 --- a/tools/fakedatabase/create_test_api_database.py +++ b/tools/fakedatabase/create_test_api_database.py @@ -8,7 +8,9 @@ """ import datetime +import os import random +import shutil import time import sys @@ -353,6 +355,19 @@ def create_etape_apo(formsemestre: FormSemestre): db.session.commit() +def create_logos(): + if not os.path.exists("/opt/scodoc-data/config/logos/logos_1"): + os.mkdir("/opt/scodoc-data/config/logos/logos_1") + shutil.copy( + "/opt/scodoc/app/static/icons/scologo_img.png", + "/opt/scodoc-data/config/logos/logos_1/logo_demo.png", + ) + shutil.copy( + "/opt/scodoc/app/static/icons/scologo_img.png", + "/opt/scodoc-data/config/logos/logo_demo.png", + ) + + def init_test_database(): """Appelé par la commande `flask init-test-database` @@ -373,6 +388,7 @@ def init_test_database(): saisie_notes_evaluations(formsemestre, user_lecteur) add_absences(formsemestre) create_etape_apo(formsemestre) + create_logos() # à compléter # - groupes # - absences