From ef96277365221caaf242008425896b9cf7725b84 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 10 Sep 2023 21:16:31 +0200 Subject: [PATCH] Option de config globale pour interdire l'export des bulletins PDF. Implements #715 --- app/api/etudiants.py | 5 +++-- app/but/bulletin_but_pdf.py | 3 +++ app/forms/main/config_main.py | 9 +++++++++ app/models/config.py | 23 +++++++++++++++++++++++ app/scodoc/gen_tables.py | 3 +-- app/scodoc/sco_bulletins_generator.py | 8 +++++++- app/scodoc/sco_utils.py | 4 +--- 7 files changed, 47 insertions(+), 8 deletions(-) diff --git a/app/api/etudiants.py b/app/api/etudiants.py index 572f77ca4..5c0c981bb 100755 --- a/app/api/etudiants.py +++ b/app/api/etudiants.py @@ -27,6 +27,7 @@ from app.models import ( FormSemestreInscription, FormSemestre, Identite, + ScoDocSiteConfig, ) from app.scodoc import sco_bulletins from app.scodoc import sco_groups @@ -359,7 +360,7 @@ def bulletin( with_img_signatures_pdf: bool = True, ): """ - Retourne le bulletin d'un étudiant en fonction de son id et d'un semestre donné + Retourne le bulletin d'un étudiant dans un formsemestre. formsemestre_id : l'id d'un formsemestre code_type : "etudid", "nip" ou "ine" @@ -376,7 +377,7 @@ def bulletin( formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404() dept = Departement.query.filter_by(id=formsemestre.dept_id).first_or_404() if g.scodoc_dept and dept.acronym != g.scodoc_dept: - return json_error(404, "formsemestre inexistant", as_response=True) + return json_error(404, "formsemestre inexistant") app.set_sco_dept(dept.acronym) if code_type == "nip": diff --git a/app/but/bulletin_but_pdf.py b/app/but/bulletin_but_pdf.py index c52c44311..82750d206 100644 --- a/app/but/bulletin_but_pdf.py +++ b/app/but/bulletin_but_pdf.py @@ -24,6 +24,7 @@ from reportlab.lib.colors import blue from reportlab.lib.units import cm, mm from reportlab.platypus import Paragraph, Spacer +from app.models import ScoDocSiteConfig from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard from app.scodoc import gen_tables from app.scodoc.codes_cursus import UE_SPORT @@ -48,6 +49,8 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard): - en HTML: une chaine - en PDF: une liste d'objets PLATYPUS (eg instance de Table). """ + if fmt == "pdf" and ScoDocSiteConfig.is_bul_pdf_disabled(): + return [Paragraph("

Export des PDF interdit par l'administrateur

")] tables_infos = [ # ---- TABLE SYNTHESE UES self.but_table_synthese_ues(), diff --git a/app/forms/main/config_main.py b/app/forms/main/config_main.py index f9eff362d..cb6b0ba22 100644 --- a/app/forms/main/config_main.py +++ b/app/forms/main/config_main.py @@ -76,6 +76,7 @@ class ScoDocConfigurationForm(FlaskForm): Attention: si ce champ peut aussi être défini dans chaque département.""", validators=[Optional(), Email()], ) + disable_bul_pdf = BooleanField("empêcher tous les exports PDF (!)") submit_scodoc = SubmitField("Valider") cancel_scodoc = SubmitField("Annuler", render_kw={"formnovalidate": True}) @@ -94,6 +95,7 @@ def configuration(): "month_debut_annee_scolaire": ScoDocSiteConfig.get_month_debut_annee_scolaire(), "month_debut_periode2": ScoDocSiteConfig.get_month_debut_periode2(), "email_from_addr": ScoDocSiteConfig.get("email_from_addr"), + "disable_bul_pdf": ScoDocSiteConfig.is_bul_pdf_disabled(), } ) if request.method == "POST" and ( @@ -139,6 +141,13 @@ def configuration(): ) if ScoDocSiteConfig.set("email_from_addr", form_scodoc.data["email_from_addr"]): flash("Adresse email origine enregistrée") + if ScoDocSiteConfig.disable_bul_pdf( + enabled=form_scodoc.data["disable_bul_pdf"] + ): + flash( + "Exports PDF " + + ("désactivés" if form_scodoc.data["disable_bul_pdf"] else "réactivés") + ) return redirect(url_for("scodoc.index")) return render_template( diff --git a/app/models/config.py b/app/models/config.py index c436248fc..e54cda781 100644 --- a/app/models/config.py +++ b/app/models/config.py @@ -95,6 +95,7 @@ class ScoDocSiteConfig(db.Model): "enable_entreprises": bool, "month_debut_annee_scolaire": int, "month_debut_periode2": int, + "disable_bul_pdf": bool, # CAS "cas_enable": bool, "cas_server": str, @@ -235,6 +236,12 @@ class ScoDocSiteConfig(db.Model): cfg = ScoDocSiteConfig.query.filter_by(name="enable_entreprises").first() return cfg is not None and cfg.value + @classmethod + def is_bul_pdf_disabled(cls) -> bool: + """True si on interdit les exports PDF des bulltins""" + cfg = ScoDocSiteConfig.query.filter_by(name="disable_bul_pdf").first() + return cfg is not None and cfg.value + @classmethod def enable_entreprises(cls, enabled=True) -> bool: """Active (ou déactive) le module entreprises. True si changement.""" @@ -251,6 +258,22 @@ class ScoDocSiteConfig(db.Model): return True return False + @classmethod + def disable_bul_pdf(cls, enabled=True) -> bool: + """Interedit (ou autorise) les exports PDF. True si changement.""" + if enabled != ScoDocSiteConfig.is_bul_pdf_disabled(): + cfg = ScoDocSiteConfig.query.filter_by(name="disable_bul_pdf").first() + if cfg is None: + cfg = ScoDocSiteConfig( + name="disable_bul_pdf", value="on" if enabled else "" + ) + else: + cfg.value = "on" if enabled else "" + db.session.add(cfg) + db.session.commit() + return True + return False + @classmethod def get(cls, name: str, default: str = "") -> str: "Get configuration param; empty string or specified default if unset" diff --git a/app/scodoc/gen_tables.py b/app/scodoc/gen_tables.py index 0920b81f5..7647f3e4c 100644 --- a/app/scodoc/gen_tables.py +++ b/app/scodoc/gen_tables.py @@ -778,8 +778,7 @@ if __name__ == "__main__": print(table.gen(format="json")) # Test pdf: import io - from reportlab.platypus import KeepInFrame - from app.scodoc import sco_preferences, sco_pdf + from app.scodoc import sco_preferences preferences = sco_preferences.SemPreferences() table.preferences = preferences diff --git a/app/scodoc/sco_bulletins_generator.py b/app/scodoc/sco_bulletins_generator.py index bf6660d8f..2229a37da 100644 --- a/app/scodoc/sco_bulletins_generator.py +++ b/app/scodoc/sco_bulletins_generator.py @@ -62,7 +62,7 @@ from reportlab.platypus import Table, TableStyle, Image, KeepInFrame from flask import request from flask_login import current_user -from app.models import FormSemestre, Identite +from app.models import FormSemestre, Identite, ScoDocSiteConfig from app.scodoc import sco_utils as scu from app.scodoc.sco_exceptions import NoteProcessError from app import log @@ -197,6 +197,10 @@ class BulletinGenerator: else: # Insere notre marqueur qui permet de générer les bookmarks et filigrannes: story.insert(index_obj_debut, marque_debut_bulletin) + + if ScoDocSiteConfig.is_bul_pdf_disabled(): + story = [Paragraph("

Export des PDF interdit par l'administrateur

")] + # # objects.append(sco_pdf.FinBulletin()) if not stand_alone: @@ -290,6 +294,8 @@ def make_formsemestre_bulletin_etud( gen_class = bulletin_get_class(bul_class_name + "BUT") if gen_class is None: gen_class = bulletin_get_class(bul_class_name) + if gen_class is not None: + break if gen_class is None: raise ValueError(f"Type de bulletin PDF invalide (paramètre: {bul_class_name})") diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 00f0604ef..7cbc3e0d2 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -1035,9 +1035,7 @@ def get_request_args(): def json_error(status_code, message=None) -> Response: - """Simple JSON for errors. - If as-response, returns Flask's Response. Otherwise returns a dict. - """ + """Simple JSON for errors.""" payload = { "error": HTTP_STATUS_CODES.get(status_code, "Unknown error"), "status": status_code,