From 63b28a327715ef8ae78b530b50f1eaec204b3458 Mon Sep 17 00:00:00 2001 From: Lyanis Souidi Date: Thu, 23 May 2024 00:15:32 +0200 Subject: [PATCH 1/4] Ajout d'un formulaire de rapport de bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Formulaire permettant de saisir un rapport de bug et de l'envoyer sur une nouvelle API scodoc.org - Modification du lien de la page d'accueil pour pointer vers le formulaire de rapport de bug au lieu de simplement dump - Après un échange avec l'API scodoc.org (pour l'upload de dump et la création de ticket), on tente de récuperer le champ json "message" pour l'afficher à l'utilisateur --- app/scodoc/sco_bug_report.py | 97 +++++++++++++++++++++++++++++ app/scodoc/sco_dump_db.py | 5 +- app/scodoc/sco_utils.py | 1 + app/templates/scolar/index.j2 | 2 +- app/views/scolar.py | 113 +++++++++++++++++++++++++++++----- 5 files changed, 198 insertions(+), 20 deletions(-) create mode 100644 app/scodoc/sco_bug_report.py diff --git a/app/scodoc/sco_bug_report.py b/app/scodoc/sco_bug_report.py new file mode 100644 index 00000000..3c4fdee0 --- /dev/null +++ b/app/scodoc/sco_bug_report.py @@ -0,0 +1,97 @@ +# -*- mode: python -*- +# -*- coding: utf-8 -*- + +############################################################################## +# +# Gestion scolarite IUT +# +# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Emmanuel Viennet emmanuel.viennet@viennet.net +# +############################################################################## + +"""Rapport de bug ScoDoc + +Permet de créer un rapport de bug (ticket) sur la plateforme git scodoc.org. + +Le principe est le suivant: + 1- Si l'utilisateur le demande, on dump la base de données et on l'envoie + + 2- ScoDoc envoie une requête POST à scodoc.org pour qu'un ticket git soit créé avec les + informations fournies par l'utilisateur + quelques métadonnées. + +""" + +import app.scodoc.sco_utils as scu, sco_version, requests +from flask import g +from flask_login import current_user +from app import log +from app.scodoc.sco_exceptions import ScoValueError +from app.scodoc.sco_dump_db import sco_dump_and_send_db + + +def sco_bug_report( + title: str = "", message: str = "", etab: str = "", include_dump: bool = False +) -> requests.Response: + dump_id = None + + if include_dump: + dump = sco_dump_and_send_db() + + try: + dump_id = dump.json()["dump_id"] + except (requests.exceptions.JSONDecodeError, KeyError): + dump_id = "inconnu" + + try: + r = requests.post( + scu.SCO_BUG_REPORT_URL, + json={ + "ticket": { + "title": title, + "message": message, + "etab": etab, + "dept": getattr(g, "scodoc_dept", "-"), + }, + "user": { + "name": current_user.get_nomcomplet(), + "email": current_user.email, + }, + "dump": { + "included": include_dump, + "id": dump_id, + }, + "scodoc": { + "version": sco_version.SCOVERSION, + }, + }, + timeout=scu.SCO_ORG_TIMEOUT, + ) + + except (requests.exceptions.ConnectionError, requests.exceptions.Timeout) as exc: + log("ConnectionError: Impossible de joindre le serveur d'assistance") + raise ScoValueError( + """ + Impossible de joindre le serveur d'assistance (scodoc.org). + Veuillez contacter le service informatique de votre établissement pour + corriger la configuration de ScoDoc. Dans la plupart des cas, il + s'agit d'un proxy mal configuré. + """ + ) from exc + + return r diff --git a/app/scodoc/sco_dump_db.py b/app/scodoc/sco_dump_db.py index 1bef5439..b7a5f8ab 100644 --- a/app/scodoc/sco_dump_db.py +++ b/app/scodoc/sco_dump_db.py @@ -67,7 +67,7 @@ SCO_DUMP_LOCK = "/tmp/scodump.lock" def sco_dump_and_send_db( message: str = "", request_url: str = "", traceback_str_base64: str = "" -): +) -> requests.Response: """Dump base de données et l'envoie anonymisée pour debug""" traceback_str = base64.urlsafe_b64decode(traceback_str_base64).decode( scu.SCO_ENCODING @@ -97,7 +97,6 @@ def sco_dump_and_send_db( # Send r = _send_db(ano_db_name, message, request_url, traceback_str=traceback_str) - code = r.status_code finally: # Drop anonymized database @@ -107,7 +106,7 @@ def sco_dump_and_send_db( log("sco_dump_and_send_db: done.") - return code + return r def _duplicate_db(db_name, ano_db_name): diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 4178c0de..f4130cb4 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -719,6 +719,7 @@ SCO_DEV_MAIL = "emmanuel.viennet@gmail.com" # SVP ne pas changer # ne pas changer (ou vous perdez le support) SCO_DUMP_UP_URL = "https://scodoc.org/scodoc-installmgr/upload-dump" SCO_UP2DATE = "https://scodoc.org/scodoc-installmgr/check_version" +SCO_BUG_REPORT_URL = "https://scodoc.org/scodoc-installmgr/report" SCO_ORG_TIMEOUT = 180 # contacts scodoc.org SCO_EXT_TIMEOUT = 180 # appels à des ressources extérieures (siret, ...) SCO_TEST_API_TIMEOUT = 5 # pour tests unitaires API diff --git a/app/templates/scolar/index.j2 b/app/templates/scolar/index.j2 index 74cd8a42..21d67fe8 100644 --- a/app/templates/scolar/index.j2 +++ b/app/templates/scolar/index.j2 @@ -297,7 +297,7 @@ div.effectif { rel="noopener noreferrer">Contact (Discord)
  • - Envoyer données + Créer un ticket
  • diff --git a/app/views/scolar.py b/app/views/scolar.py index de147fee..19331685 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -85,6 +85,7 @@ from app.scodoc import ( html_sco_header, sco_import_etuds, sco_archives_etud, + sco_bug_report, sco_cache, sco_debouche, sco_dept, @@ -2534,25 +2535,105 @@ def stat_bac(formsemestre_id): def sco_dump_and_send_db(message="", request_url="", traceback_str_base64=""): "Send anonymized data to supervision" - status_code = sco_dump_db.sco_dump_and_send_db( + r = sco_dump_db.sco_dump_and_send_db( message, request_url, traceback_str_base64=traceback_str_base64 ) + + status_code = r.status_code + + try: + r_msg = r.json()["message"] + except (requests.exceptions.JSONDecodeError, KeyError): + r_msg = "Erreur: code " + +status_code + +' Merci de contacter ' + +scu.SCO_DEV_MAIL + +"" + H = [html_sco_header.sco_header(page_title="Assistance technique")] - if status_code == requests.codes.INSUFFICIENT_STORAGE: # pylint: disable=no-member - H.append( - """

    - Erreur: espace serveur trop plein. - Merci de contacter {0}

    """.format( - scu.SCO_DEV_MAIL - ) - ) - elif status_code == requests.codes.OK: # pylint: disable=no-member - H.append("""

    Opération effectuée.

    """) + if status_code == requests.codes.OK: # pylint: disable=no-member + H.append(f"""

    Opération effectuée.

    {r_msg}

    """) else: - H.append( - f"""

    - Erreur: code {status_code} - Merci de contacter {scu.SCO_DEV_MAIL}

    """ - ) + H.append(f"""

    {r_msg}

    """) flash("Données envoyées au serveur d'assistance") return "\n".join(H) + html_sco_header.sco_footer() + + +# --- Report form (assistance) +@bp.route("/sco_bug_report", methods=["GET"]) +@scodoc +@permission_required(Permission.ScoView) +@scodoc7func +def sco_bug_report_form(): + "Formulaire de création d'un ticket d'assistance" + + H = [ + html_sco_header.sco_header(page_title="Assistance technique"), + """

    Assistance technique

    +

    + Ce formulaire permet d'effectuer une demande d'assistance technique.
    + Son contenu sera accessible publiquement sur scodoc.org, veuillez donc ne pas y inclure d'informations sensibles.
    + L'adresse email associée à votre compte ScoDoc est automatiquement transmise avec votre demande mais ne sera pas + affichée publiquement.
    +

    +
    + *
    +
    + *
    +
    +
    + """, + ] + + H.append( + '
    ' + ) + + H.append( + """ + +

    + +
    + """ + ) + + return "\n".join(H) + html_sco_header.sco_footer() + + +# --- Report create (assistance) +@bp.route("/sco_bug_report", methods=["POST"]) +@scodoc +@permission_required(Permission.ScoView) +@scodoc7func +def sco_bug_report_create(title=None, message=None, etab="", include_dump=False): + "Création d'un ticket d'assistance" + + if not title or not message: + flash("Les champs titre et message sont obligatoires.") + return flask.redirect(url_for("scolar.sco_bug_report")) + + r = sco_bug_report.sco_bug_report(title, message, etab, include_dump) + + status_code = r.status_code + try: + r_msg = r.json()["message"] + except (requests.exceptions.JSONDecodeError, KeyError): + r_msg = "Erreur: code " + +status_code + +' Merci de contacter ' + +scu.SCO_DEV_MAIL + +"" + + H = [html_sco_header.sco_header(page_title="Assistance technique")] + if r.status_code >= 200 and r.status_code < 300: + H.append(f"""

    Opération effectuée.

    {r_msg}

    """) + else: + H.append(f"""

    {r_msg}

    """) + return "\n".join(H) + html_sco_header.sco_footer() From dc095765f28d958d96f66d48cc3b15b926b6d8a2 Mon Sep 17 00:00:00 2001 From: Lyanis Souidi Date: Thu, 23 May 2024 16:21:12 +0200 Subject: [PATCH 2/4] =?UTF-8?q?Retrait=20d=C3=A9corateur=20inutile?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le décorateur `@scodoc7func` n'est pas utile pour cette vue, il est retiré. --- app/views/scolar.py | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/scolar.py b/app/views/scolar.py index 19331685..87896d92 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -2565,7 +2565,6 @@ def sco_dump_and_send_db(message="", request_url="", traceback_str_base64=""): @bp.route("/sco_bug_report", methods=["GET"]) @scodoc @permission_required(Permission.ScoView) -@scodoc7func def sco_bug_report_form(): "Formulaire de création d'un ticket d'assistance" From af1d1884c7a35db1558d10fc992c3c814e97d848 Mon Sep 17 00:00:00 2001 From: Lyanis Souidi Date: Fri, 24 May 2024 13:01:56 +0200 Subject: [PATCH 3/4] Template/wtf form pour bug report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ajout d'un template pour gérer le formulaire et utilisation de WTF form pour la validation des données. --- app/forms/main/create_bug_report.py | 64 ++++++++++++++++++ app/templates/sco_bug_report.j2 | 19 ++++++ app/views/scolar.py | 100 +++++++++------------------- 3 files changed, 116 insertions(+), 67 deletions(-) create mode 100644 app/forms/main/create_bug_report.py create mode 100644 app/templates/sco_bug_report.j2 diff --git a/app/forms/main/create_bug_report.py b/app/forms/main/create_bug_report.py new file mode 100644 index 00000000..5e354192 --- /dev/null +++ b/app/forms/main/create_bug_report.py @@ -0,0 +1,64 @@ +# -*- mode: python -*- +# -*- coding: utf-8 -*- + +############################################################################## +# +# ScoDoc +# +# Copyright (c) 1999 - 2024 Emmanuel Viennet. All rights reserved. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# Emmanuel Viennet emmanuel.viennet@viennet.net +# +############################################################################## + +""" +Formulaire création de ticket de bug +""" + +from flask_wtf import FlaskForm +from wtforms import SubmitField, validators +from wtforms.fields.simple import StringField, TextAreaField, BooleanField +from app.scodoc import sco_preferences + + +class CreateBugReport(FlaskForm): + """Formulaire permettant la création d'un ticket de bug""" + + title = StringField( + label="Titre du ticket", + validators=[ + validators.DataRequired("titre du ticket requis"), + ], + ) + message = TextAreaField( + label="Message", + id="ticket_message", + validators=[ + validators.DataRequired("message du ticket requis"), + ], + ) + etab = StringField(label="Etablissement") + include_dump = BooleanField( + "Inclure une copie anonymisée de la base de données ? (ces données permettent aux développeur·euse·s de reproduire l'erreur rencontrée)", + default=False, + ) + submit = SubmitField("Envoyer") + cancel = SubmitField("Annuler", render_kw={"formnovalidate": True}) + + def __init__(self, *args, **kwargs): + super(CreateBugReport, self).__init__(*args, **kwargs) + self.etab.data = sco_preferences.get_preference("InstituteName") or "" diff --git a/app/templates/sco_bug_report.j2 b/app/templates/sco_bug_report.j2 new file mode 100644 index 00000000..07bd189c --- /dev/null +++ b/app/templates/sco_bug_report.j2 @@ -0,0 +1,19 @@ +{# -*- mode: jinja-html -*- #} +{% extends 'base.j2' %} +{% import 'wtf.j2' as wtf %} + +{% block app_content %} +

    Assistance technique

    +

    + Ce formulaire permet d'effectuer une demande d'assistance technique.
    + Son contenu sera accessible publiquement sur scodoc.org, veuillez donc ne pas y inclure d'informations sensibles.
    + L'adresse email associée à votre compte ScoDoc est automatiquement transmise avec votre demande mais ne sera pas + affichée publiquement.
    +

    + +
    +
    + {{ wtf.quick_form(form) }} +
    +
    +{% endblock app_content %} diff --git a/app/views/scolar.py b/app/views/scolar.py index 87896d92..b9953863 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -110,6 +110,7 @@ from app.scodoc import ( sco_up_to_date, ) from app.tables import list_etuds +from app.forms.main.create_bug_report import CreateBugReport def sco_publish(route, function, permission, methods=["GET"]): @@ -2562,77 +2563,42 @@ def sco_dump_and_send_db(message="", request_url="", traceback_str_base64=""): # --- Report form (assistance) -@bp.route("/sco_bug_report", methods=["GET"]) +@bp.route("/sco_bug_report", methods=["GET", "POST"]) @scodoc @permission_required(Permission.ScoView) def sco_bug_report_form(): "Formulaire de création d'un ticket d'assistance" - H = [ - html_sco_header.sco_header(page_title="Assistance technique"), - """

    Assistance technique

    -

    - Ce formulaire permet d'effectuer une demande d'assistance technique.
    - Son contenu sera accessible publiquement sur scodoc.org, veuillez donc ne pas y inclure d'informations sensibles.
    - L'adresse email associée à votre compte ScoDoc est automatiquement transmise avec votre demande mais ne sera pas - affichée publiquement.
    -

    -
    - *
    -
    - *
    -
    -
    - """, - ] + form = CreateBugReport() + if request.method == "POST" and form.cancel.data: # cancel button + return redirect(url_for("scodoc.index")) + if form.validate_on_submit(): + r = sco_bug_report.sco_bug_report( + form.title.data, form.message.data, form.etab.data, form.include_dump.data + ) - H.append( - '
    ' + status_code = r.status_code + try: + r_msg = r.json()["message"] + except (requests.exceptions.JSONDecodeError, KeyError): + r_msg = ( + "Erreur: code " + + str(status_code) + + ' Merci de contacter ' + + scu.SCO_DEV_MAIL + + "" + ) + + H = [html_sco_header.sco_header(page_title="Assistance technique")] + if r.status_code >= 200 and r.status_code < 300: + H.append(f"""

    Opération effectuée.

    {r_msg}

    """) + else: + H.append(f"""

    {r_msg}

    """) + return "\n".join(H) + html_sco_header.sco_footer() + + return render_template( + "sco_bug_report.j2", + form=form, ) - - H.append( - """ - -

    - -
    - """ - ) - - return "\n".join(H) + html_sco_header.sco_footer() - - -# --- Report create (assistance) -@bp.route("/sco_bug_report", methods=["POST"]) -@scodoc -@permission_required(Permission.ScoView) -@scodoc7func -def sco_bug_report_create(title=None, message=None, etab="", include_dump=False): - "Création d'un ticket d'assistance" - - if not title or not message: - flash("Les champs titre et message sont obligatoires.") - return flask.redirect(url_for("scolar.sco_bug_report")) - - r = sco_bug_report.sco_bug_report(title, message, etab, include_dump) - - status_code = r.status_code - try: - r_msg = r.json()["message"] - except (requests.exceptions.JSONDecodeError, KeyError): - r_msg = "Erreur: code " - +status_code - +' Merci de contacter ' - +scu.SCO_DEV_MAIL - +"" - - H = [html_sco_header.sco_header(page_title="Assistance technique")] - if r.status_code >= 200 and r.status_code < 300: - H.append(f"""

    Opération effectuée.

    {r_msg}

    """) - else: - H.append(f"""

    {r_msg}

    """) - return "\n".join(H) + html_sco_header.sco_footer() From 2745ffd687ebbe06e8e1adf56e306509a765dc95 Mon Sep 17 00:00:00 2001 From: Emmanuel Viennet Date: Sun, 26 May 2024 22:57:04 +0200 Subject: [PATCH 4/4] Bug report: corrections mineures --- app/forms/main/create_bug_report.py | 4 +++- app/scodoc/sco_bug_report.py | 13 +++++++++---- app/templates/scolar/index.j2 | 5 ++++- app/views/scolar.py | 16 ++++++---------- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/app/forms/main/create_bug_report.py b/app/forms/main/create_bug_report.py index 5e354192..e94920f8 100644 --- a/app/forms/main/create_bug_report.py +++ b/app/forms/main/create_bug_report.py @@ -53,7 +53,9 @@ class CreateBugReport(FlaskForm): ) etab = StringField(label="Etablissement") include_dump = BooleanField( - "Inclure une copie anonymisée de la base de données ? (ces données permettent aux développeur·euse·s de reproduire l'erreur rencontrée)", + """Inclure une copie anonymisée de la base de données ? + Ces données faciliteront le traitement du problème et resteront strictement confidentielles. + """, default=False, ) submit = SubmitField("Envoyer") diff --git a/app/scodoc/sco_bug_report.py b/app/scodoc/sco_bug_report.py index 3c4fdee0..c7df1a11 100644 --- a/app/scodoc/sco_bug_report.py +++ b/app/scodoc/sco_bug_report.py @@ -36,18 +36,22 @@ Le principe est le suivant: informations fournies par l'utilisateur + quelques métadonnées. """ - -import app.scodoc.sco_utils as scu, sco_version, requests from flask import g from flask_login import current_user +import requests + +import app.scodoc.sco_utils as scu +import sco_version + from app import log -from app.scodoc.sco_exceptions import ScoValueError from app.scodoc.sco_dump_db import sco_dump_and_send_db +from app.scodoc.sco_exceptions import ScoValueError def sco_bug_report( title: str = "", message: str = "", etab: str = "", include_dump: bool = False ) -> requests.Response: + """Envoi d'un bug report (ticket)""" dump_id = None if include_dump: @@ -56,8 +60,9 @@ def sco_bug_report( try: dump_id = dump.json()["dump_id"] except (requests.exceptions.JSONDecodeError, KeyError): - dump_id = "inconnu" + dump_id = "inconnu (erreur)" + log(f"sco_bug_report: {scu.SCO_BUG_REPORT_URL} by {current_user.user_name}") try: r = requests.post( scu.SCO_BUG_REPORT_URL, diff --git a/app/templates/scolar/index.j2 b/app/templates/scolar/index.j2 index 21d67fe8..2c3584a5 100644 --- a/app/templates/scolar/index.j2 +++ b/app/templates/scolar/index.j2 @@ -297,7 +297,10 @@ div.effectif { rel="noopener noreferrer">Contact (Discord)
  • - Créer un ticket + Envoyer données +
  • +
  • + Signaler une erreur ou suggérer une amélioration
  • diff --git a/app/views/scolar.py b/app/views/scolar.py index b9953863..0cb128ae 100644 --- a/app/views/scolar.py +++ b/app/views/scolar.py @@ -2571,7 +2571,7 @@ def sco_bug_report_form(): form = CreateBugReport() if request.method == "POST" and form.cancel.data: # cancel button - return redirect(url_for("scodoc.index")) + return flask.redirect(url_for("scodoc.index")) if form.validate_on_submit(): r = sco_bug_report.sco_bug_report( form.title.data, form.message.data, form.etab.data, form.include_dump.data @@ -2581,15 +2581,11 @@ def sco_bug_report_form(): try: r_msg = r.json()["message"] except (requests.exceptions.JSONDecodeError, KeyError): - r_msg = ( - "Erreur: code " - + str(status_code) - + ' Merci de contacter ' - + scu.SCO_DEV_MAIL - + "" - ) + log(f"sco_bug_report: error {status_code}") + r_msg = f"""Erreur: code {status_code} + Merci de contacter + {scu.SCO_DEV_MAIL} + """ H = [html_sco_header.sco_header(page_title="Assistance technique")] if r.status_code >= 200 and r.status_code < 300: