Option de config globale pour interdire l'export des bulletins PDF. Implements #715

This commit is contained in:
Emmanuel Viennet 2023-09-10 21:16:31 +02:00
parent 08c8a06965
commit ef96277365
7 changed files with 47 additions and 8 deletions

View File

@ -27,6 +27,7 @@ from app.models import (
FormSemestreInscription, FormSemestreInscription,
FormSemestre, FormSemestre,
Identite, Identite,
ScoDocSiteConfig,
) )
from app.scodoc import sco_bulletins from app.scodoc import sco_bulletins
from app.scodoc import sco_groups from app.scodoc import sco_groups
@ -359,7 +360,7 @@ def bulletin(
with_img_signatures_pdf: bool = True, 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 formsemestre_id : l'id d'un formsemestre
code_type : "etudid", "nip" ou "ine" code_type : "etudid", "nip" ou "ine"
@ -376,7 +377,7 @@ def bulletin(
formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404() formsemestre = FormSemestre.query.filter_by(id=formsemestre_id).first_or_404()
dept = Departement.query.filter_by(id=formsemestre.dept_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: 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) app.set_sco_dept(dept.acronym)
if code_type == "nip": if code_type == "nip":

View File

@ -24,6 +24,7 @@ from reportlab.lib.colors import blue
from reportlab.lib.units import cm, mm from reportlab.lib.units import cm, mm
from reportlab.platypus import Paragraph, Spacer from reportlab.platypus import Paragraph, Spacer
from app.models import ScoDocSiteConfig
from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard from app.scodoc.sco_bulletins_standard import BulletinGeneratorStandard
from app.scodoc import gen_tables from app.scodoc import gen_tables
from app.scodoc.codes_cursus import UE_SPORT from app.scodoc.codes_cursus import UE_SPORT
@ -48,6 +49,8 @@ class BulletinGeneratorStandardBUT(BulletinGeneratorStandard):
- en HTML: une chaine - en HTML: une chaine
- en PDF: une liste d'objets PLATYPUS (eg instance de Table). - en PDF: une liste d'objets PLATYPUS (eg instance de Table).
""" """
if fmt == "pdf" and ScoDocSiteConfig.is_bul_pdf_disabled():
return [Paragraph("<p>Export des PDF interdit par l'administrateur</p>")]
tables_infos = [ tables_infos = [
# ---- TABLE SYNTHESE UES # ---- TABLE SYNTHESE UES
self.but_table_synthese_ues(), self.but_table_synthese_ues(),

View File

@ -76,6 +76,7 @@ class ScoDocConfigurationForm(FlaskForm):
Attention: si ce champ peut aussi être défini dans chaque département.""", Attention: si ce champ peut aussi être défini dans chaque département.""",
validators=[Optional(), Email()], validators=[Optional(), Email()],
) )
disable_bul_pdf = BooleanField("empêcher <em>tous</em> les exports PDF (!)")
submit_scodoc = SubmitField("Valider") submit_scodoc = SubmitField("Valider")
cancel_scodoc = SubmitField("Annuler", render_kw={"formnovalidate": True}) 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_annee_scolaire": ScoDocSiteConfig.get_month_debut_annee_scolaire(),
"month_debut_periode2": ScoDocSiteConfig.get_month_debut_periode2(), "month_debut_periode2": ScoDocSiteConfig.get_month_debut_periode2(),
"email_from_addr": ScoDocSiteConfig.get("email_from_addr"), "email_from_addr": ScoDocSiteConfig.get("email_from_addr"),
"disable_bul_pdf": ScoDocSiteConfig.is_bul_pdf_disabled(),
} }
) )
if request.method == "POST" and ( if request.method == "POST" and (
@ -139,6 +141,13 @@ def configuration():
) )
if ScoDocSiteConfig.set("email_from_addr", form_scodoc.data["email_from_addr"]): if ScoDocSiteConfig.set("email_from_addr", form_scodoc.data["email_from_addr"]):
flash("Adresse email origine enregistrée") 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 redirect(url_for("scodoc.index"))
return render_template( return render_template(

View File

@ -95,6 +95,7 @@ class ScoDocSiteConfig(db.Model):
"enable_entreprises": bool, "enable_entreprises": bool,
"month_debut_annee_scolaire": int, "month_debut_annee_scolaire": int,
"month_debut_periode2": int, "month_debut_periode2": int,
"disable_bul_pdf": bool,
# CAS # CAS
"cas_enable": bool, "cas_enable": bool,
"cas_server": str, "cas_server": str,
@ -235,6 +236,12 @@ class ScoDocSiteConfig(db.Model):
cfg = ScoDocSiteConfig.query.filter_by(name="enable_entreprises").first() cfg = ScoDocSiteConfig.query.filter_by(name="enable_entreprises").first()
return cfg is not None and cfg.value 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 @classmethod
def enable_entreprises(cls, enabled=True) -> bool: def enable_entreprises(cls, enabled=True) -> bool:
"""Active (ou déactive) le module entreprises. True si changement.""" """Active (ou déactive) le module entreprises. True si changement."""
@ -251,6 +258,22 @@ class ScoDocSiteConfig(db.Model):
return True return True
return False 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 @classmethod
def get(cls, name: str, default: str = "") -> str: def get(cls, name: str, default: str = "") -> str:
"Get configuration param; empty string or specified default if unset" "Get configuration param; empty string or specified default if unset"

View File

@ -778,8 +778,7 @@ if __name__ == "__main__":
print(table.gen(format="json")) print(table.gen(format="json"))
# Test pdf: # Test pdf:
import io import io
from reportlab.platypus import KeepInFrame from app.scodoc import sco_preferences
from app.scodoc import sco_preferences, sco_pdf
preferences = sco_preferences.SemPreferences() preferences = sco_preferences.SemPreferences()
table.preferences = preferences table.preferences = preferences

View File

@ -62,7 +62,7 @@ from reportlab.platypus import Table, TableStyle, Image, KeepInFrame
from flask import request from flask import request
from flask_login import current_user 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 import sco_utils as scu
from app.scodoc.sco_exceptions import NoteProcessError from app.scodoc.sco_exceptions import NoteProcessError
from app import log from app import log
@ -197,6 +197,10 @@ class BulletinGenerator:
else: else:
# Insere notre marqueur qui permet de générer les bookmarks et filigrannes: # Insere notre marqueur qui permet de générer les bookmarks et filigrannes:
story.insert(index_obj_debut, marque_debut_bulletin) story.insert(index_obj_debut, marque_debut_bulletin)
if ScoDocSiteConfig.is_bul_pdf_disabled():
story = [Paragraph("<p>Export des PDF interdit par l'administrateur</p>")]
# #
# objects.append(sco_pdf.FinBulletin()) # objects.append(sco_pdf.FinBulletin())
if not stand_alone: if not stand_alone:
@ -290,6 +294,8 @@ def make_formsemestre_bulletin_etud(
gen_class = bulletin_get_class(bul_class_name + "BUT") gen_class = bulletin_get_class(bul_class_name + "BUT")
if gen_class is None: if gen_class is None:
gen_class = bulletin_get_class(bul_class_name) gen_class = bulletin_get_class(bul_class_name)
if gen_class is not None:
break
if gen_class is None: if gen_class is None:
raise ValueError(f"Type de bulletin PDF invalide (paramètre: {bul_class_name})") raise ValueError(f"Type de bulletin PDF invalide (paramètre: {bul_class_name})")

View File

@ -1035,9 +1035,7 @@ def get_request_args():
def json_error(status_code, message=None) -> Response: def json_error(status_code, message=None) -> Response:
"""Simple JSON for errors. """Simple JSON for errors."""
If as-response, returns Flask's Response. Otherwise returns a dict.
"""
payload = { payload = {
"error": HTTP_STATUS_CODES.get(status_code, "Unknown error"), "error": HTTP_STATUS_CODES.get(status_code, "Unknown error"),
"status": status_code, "status": status_code,