forked from ScoDoc/ScoDoc
Améliore validation des dates et des ids
This commit is contained in:
parent
00b6d19c0c
commit
b2893a3371
@ -9,6 +9,12 @@
|
||||
v 1.3 (python3)
|
||||
"""
|
||||
import html
|
||||
import re
|
||||
|
||||
# re validant dd/mm/yyyy
|
||||
DMY_REGEXP = re.compile(
|
||||
r"^(?:(?:31(\/|-|\.)(?:0?[13578]|1[02]))\1|(?:(?:29|30)(\/|-|\.)(?:0?[13-9]|1[0-2])\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.)0?2\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.)(?:(?:0?[1-9])|(?:1[0-2]))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$"
|
||||
)
|
||||
|
||||
|
||||
def TrivialFormulator(
|
||||
@ -66,8 +72,8 @@ def TrivialFormulator(
|
||||
HTML elements:
|
||||
input_type : 'text', 'textarea', 'password',
|
||||
'radio', 'menu', 'checkbox',
|
||||
'hidden', 'separator', 'file', 'date', 'boolcheckbox',
|
||||
'text_suggest'
|
||||
'hidden', 'separator', 'file', 'date', 'datedmy' (avec validation),
|
||||
'boolcheckbox', 'text_suggest'
|
||||
(default text)
|
||||
size : text field width
|
||||
rows, cols: textarea geometry
|
||||
@ -243,6 +249,8 @@ class TF(object):
|
||||
"Le champ '%s' doit être renseigné" % descr.get("title", field)
|
||||
)
|
||||
ok = 0
|
||||
elif val == "" or val == None:
|
||||
continue # allowed empty field, skip
|
||||
# type
|
||||
typ = descr.get("type", "string")
|
||||
if val != "" and val != None:
|
||||
@ -300,6 +308,10 @@ class TF(object):
|
||||
if not descr["validator"](val, field):
|
||||
msg.append("valeur invalide (%s) pour le champ '%s'" % (val, field))
|
||||
ok = 0
|
||||
elif descr.get("input_type") == "datedmy":
|
||||
if not DMY_REGEXP.match(val):
|
||||
msg.append("valeur invalide (%s) pour la date '%s'" % (val, field))
|
||||
ok = 0
|
||||
# boolean checkbox
|
||||
if descr.get("input_type", None) == "boolcheckbox":
|
||||
if int(val):
|
||||
@ -564,7 +576,9 @@ class TF(object):
|
||||
'<input type="file" name="%s" size="%s" value="%s" %s>'
|
||||
% (field, size, values[field], attribs)
|
||||
)
|
||||
elif input_type == "date": # JavaScript widget for date input
|
||||
elif (
|
||||
input_type == "date" or input_type == "datedmy"
|
||||
): # JavaScript widget for date input
|
||||
lem.append(
|
||||
'<input type="text" name="%s" size="10" value="%s" class="datepicker">'
|
||||
% (field, values[field])
|
||||
|
@ -170,7 +170,7 @@ def evaluation_create_form(
|
||||
(
|
||||
"jour",
|
||||
{
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"title": "Date",
|
||||
"size": 12,
|
||||
"explanation": "date de l'examen, devoir ou contrôle",
|
||||
|
@ -96,6 +96,28 @@ class ScoNonEmptyFormationObject(ScoValueError):
|
||||
super().__init__(msg=msg, dest_url=dest_url)
|
||||
|
||||
|
||||
class ScoInvalidIdType(ScoValueError):
|
||||
"""Pour les clients qui s'obstinnent à utiliser des bookmarks ou
|
||||
historiques anciens avec des ID ScoDoc7"""
|
||||
|
||||
def __init__(self, msg=""):
|
||||
import app.scodoc.sco_utils as scu
|
||||
|
||||
msg = f"""<h3>Adresse de page invalide</h3>
|
||||
<p class="help">
|
||||
Vous utilisez un lien invalide, qui correspond probablement
|
||||
à une ancienne version du logiciel. <br>
|
||||
Au besoin, mettre à jour vos marque-pages.
|
||||
</p>
|
||||
<p> Si le problème persiste, merci de contacter l'assistance
|
||||
via la liste de diffusion <a href="{scu.SCO_USERS_LIST}">Notes</a>
|
||||
ou le salon Discord.
|
||||
</p>
|
||||
<p>Message serveur: <tt>{msg}</tt></p>
|
||||
"""
|
||||
super().__init__(msg)
|
||||
|
||||
|
||||
class ScoGenError(ScoException):
|
||||
"exception avec affichage d'une page explicative ad-hoc"
|
||||
|
||||
|
@ -27,21 +27,22 @@
|
||||
|
||||
"""Operations de base sur les formsemestres
|
||||
"""
|
||||
from app.scodoc.sco_exceptions import ScoValueError
|
||||
import time
|
||||
from operator import itemgetter
|
||||
import time
|
||||
|
||||
from flask import g, request
|
||||
|
||||
import app
|
||||
from app import log
|
||||
from app.models import Departement
|
||||
|
||||
from app.scodoc import sco_codes_parcours
|
||||
from app.scodoc import sco_cache
|
||||
from app.scodoc import sco_formations
|
||||
from app.scodoc import sco_preferences
|
||||
from app.scodoc.gen_tables import GenTable
|
||||
from app import log
|
||||
from app.scodoc.sco_codes_parcours import NO_SEMESTRE_ID
|
||||
from app.scodoc.sco_exceptions import ScoValueError, ScoInvalidIdType
|
||||
from app.scodoc.sco_vdi import ApoEtapeVDI
|
||||
import app.scodoc.notesdb as ndb
|
||||
import app.scodoc.sco_utils as scu
|
||||
@ -97,7 +98,7 @@ def get_formsemestre(formsemestre_id, raise_soft_exc=False):
|
||||
if formsemestre_id in g.stored_get_formsemestre:
|
||||
return g.stored_get_formsemestre[formsemestre_id]
|
||||
if not isinstance(formsemestre_id, int):
|
||||
raise ValueError("formsemestre_id must be an integer !")
|
||||
raise ScoInvalidIdType("formsemestre_id must be an integer !")
|
||||
sems = do_formsemestre_list(args={"formsemestre_id": formsemestre_id})
|
||||
if not sems:
|
||||
log("get_formsemestre: invalid formsemestre_id (%s)" % formsemestre_id)
|
||||
|
@ -254,7 +254,7 @@ def do_formsemestre_createwithmodules(edit=False):
|
||||
"date_debut",
|
||||
{
|
||||
"title": "Date de début", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
@ -264,7 +264,7 @@ def do_formsemestre_createwithmodules(edit=False):
|
||||
"date_fin",
|
||||
{
|
||||
"title": "Date de fin", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
@ -914,7 +914,7 @@ def formsemestre_clone(formsemestre_id):
|
||||
"date_debut",
|
||||
{
|
||||
"title": "Date de début", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
@ -924,7 +924,7 @@ def formsemestre_clone(formsemestre_id):
|
||||
"date_fin",
|
||||
{
|
||||
"title": "Date de fin", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
|
@ -154,7 +154,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
|
||||
"date_debut",
|
||||
{
|
||||
"title": "Date de début", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a (peut être approximatif)",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
@ -164,7 +164,7 @@ def formsemestre_ext_create_form(etudid, formsemestre_id):
|
||||
"date_fin",
|
||||
{
|
||||
"title": "Date de fin", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a (peut être approximatif)",
|
||||
"size": 9,
|
||||
"allow_null": False,
|
||||
|
@ -1,42 +1,42 @@
|
||||
/* Module par Seb. L. */
|
||||
class releveBUT extends HTMLElement {
|
||||
constructor(){
|
||||
constructor() {
|
||||
super();
|
||||
this.shadow = this.attachShadow({mode: 'open'});
|
||||
this.shadow = this.attachShadow({ mode: 'open' });
|
||||
|
||||
/* Config par defaut */
|
||||
this.config = {
|
||||
showURL: true
|
||||
};
|
||||
|
||||
|
||||
/* Template du module */
|
||||
this.shadow.innerHTML = this.template();
|
||||
|
||||
|
||||
/* Style du module */
|
||||
const styles = document.createElement('link');
|
||||
styles.setAttribute('rel', 'stylesheet');
|
||||
styles.setAttribute('href', '/ScoDoc/static/css/releve-but.css');
|
||||
this.shadow.appendChild(styles);
|
||||
this.shadow.appendChild(styles);
|
||||
}
|
||||
listeOnOff() {
|
||||
this.parentElement.parentElement.classList.toggle("listeOff");
|
||||
this.parentElement.parentElement.querySelectorAll(".moduleOnOff").forEach(e=>{
|
||||
this.parentElement.parentElement.querySelectorAll(".moduleOnOff").forEach(e => {
|
||||
e.classList.remove("moduleOnOff")
|
||||
})
|
||||
}
|
||||
moduleOnOff(){
|
||||
moduleOnOff() {
|
||||
this.parentElement.classList.toggle("moduleOnOff");
|
||||
}
|
||||
goTo(){
|
||||
goTo() {
|
||||
let module = this.dataset.module;
|
||||
this.parentElement.parentElement.parentElement.parentElement.querySelector("#Module_" + module).scrollIntoView();
|
||||
}
|
||||
|
||||
set setConfig(config){
|
||||
set setConfig(config) {
|
||||
this.config.showURL = config.showURL ?? this.config.showURL;
|
||||
}
|
||||
|
||||
set showData(data) {
|
||||
set showData(data) {
|
||||
this.showInformations(data);
|
||||
this.showSemestre(data);
|
||||
this.showSynthese(data);
|
||||
@ -46,7 +46,7 @@ class releveBUT extends HTMLElement {
|
||||
|
||||
this.shadow.querySelectorAll(".CTA_Liste").forEach(e => {
|
||||
e.addEventListener("click", this.listeOnOff)
|
||||
})
|
||||
})
|
||||
this.shadow.querySelectorAll(".ue, .module").forEach(e => {
|
||||
e.addEventListener("click", this.moduleOnOff)
|
||||
})
|
||||
@ -57,7 +57,7 @@ class releveBUT extends HTMLElement {
|
||||
this.shadow.children[0].classList.add("ready");
|
||||
}
|
||||
|
||||
template(){
|
||||
template() {
|
||||
return `
|
||||
<div>
|
||||
<div class="wait"></div>
|
||||
@ -142,8 +142,8 @@ class releveBUT extends HTMLElement {
|
||||
this.shadow.querySelector(".studentPic").src = data.etudiant.photo_url || "default_Student.svg";
|
||||
|
||||
let output = '';
|
||||
|
||||
if(this.config.showURL){
|
||||
|
||||
if (this.config.showURL) {
|
||||
output += `<a href="${data.etudiant.fiche_url}" class=info_etudiant>`;
|
||||
} else {
|
||||
output += `<div class=info_etudiant>`;
|
||||
@ -167,7 +167,7 @@ class releveBUT extends HTMLElement {
|
||||
</div>
|
||||
<div>${data.formation.titre}</div>
|
||||
`;
|
||||
if(this.config.showURL){
|
||||
if (this.config.showURL) {
|
||||
output += `</a>`;
|
||||
} else {
|
||||
output += `</div>`;
|
||||
@ -190,18 +190,18 @@ class releveBUT extends HTMLElement {
|
||||
<div>Moy. promo. :</div><div>${data.semestre.notes.moy}</div>
|
||||
<div>Min. promo. :</div><div>${data.semestre.notes.min}</div>
|
||||
</div>`;
|
||||
/*${data.semestre.groupes.map(groupe => {
|
||||
return `
|
||||
<div>
|
||||
<div class=enteteSemestre>Groupe</div><div class=enteteSemestre>${groupe.nom}</div>
|
||||
<div class=rang>Rang :</div><div class=rang>${groupe.rang.value} / ${groupe.rang.total}</div>
|
||||
<div>Max. groupe :</div><div>${groupe.notes.max}</div>
|
||||
<div>Moy. groupe :</div><div>${groupe.notes.min}</div>
|
||||
<div>Min. groupe :</div><div>${groupe.notes.min}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join("")
|
||||
}*/
|
||||
/*${data.semestre.groupes.map(groupe => {
|
||||
return `
|
||||
<div>
|
||||
<div class=enteteSemestre>Groupe</div><div class=enteteSemestre>${groupe.nom}</div>
|
||||
<div class=rang>Rang :</div><div class=rang>${groupe.rang.value} / ${groupe.rang.total}</div>
|
||||
<div>Max. groupe :</div><div>${groupe.notes.max}</div>
|
||||
<div>Moy. groupe :</div><div>${groupe.notes.min}</div>
|
||||
<div>Min. groupe :</div><div>${groupe.notes.min}</div>
|
||||
</div>
|
||||
`;
|
||||
}).join("")
|
||||
}*/
|
||||
this.shadow.querySelector(".infoSemestre").innerHTML = output;
|
||||
/*this.shadow.querySelector(".decision").innerHTML = data.semestre.decision.code;*/
|
||||
}
|
||||
@ -213,6 +213,7 @@ class releveBUT extends HTMLElement {
|
||||
let output = ``;
|
||||
Object.entries(data.ues).forEach(([ue, dataUE]) => {
|
||||
output += `
|
||||
|
||||
<div>
|
||||
<div class=ue>
|
||||
<h3>
|
||||
@ -257,7 +258,7 @@ class releveBUT extends HTMLElement {
|
||||
})
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
/*******************************/
|
||||
/* Evaluations */
|
||||
/*******************************/
|
||||
@ -335,8 +336,8 @@ class releveBUT extends HTMLElement {
|
||||
/********************/
|
||||
/* Fonctions d'aide */
|
||||
/********************/
|
||||
URL(href, content){
|
||||
if(this.config.showURL){
|
||||
URL(href, content) {
|
||||
if (this.config.showURL) {
|
||||
return `<a href=${href}>${content}</a>`;
|
||||
} else {
|
||||
return content;
|
||||
|
@ -1151,8 +1151,8 @@ def AddBilletAbsenceForm(etudid):
|
||||
scu.get_request_args(),
|
||||
(
|
||||
("etudid", {"input_type": "hidden"}),
|
||||
("begin", {"input_type": "date"}),
|
||||
("end", {"input_type": "date"}),
|
||||
("begin", {"input_type": "datedmy"}),
|
||||
("end", {"input_type": "datedmy"}),
|
||||
(
|
||||
"justified",
|
||||
{"input_type": "boolcheckbox", "default": 0, "title": "Justifiée"},
|
||||
|
@ -72,12 +72,7 @@ from app import log, send_scodoc_alarm
|
||||
from app.scodoc import scolog
|
||||
from app.scodoc.scolog import logdb
|
||||
|
||||
from app.scodoc.sco_exceptions import (
|
||||
ScoValueError,
|
||||
ScoLockedFormError,
|
||||
ScoGenError,
|
||||
AccessDenied,
|
||||
)
|
||||
from app.scodoc.sco_exceptions import AccessDenied, ScoValueError, ScoInvalidIdType
|
||||
from app.scodoc import html_sco_header
|
||||
from app.pe import pe_view
|
||||
from app.scodoc import sco_abs
|
||||
@ -287,6 +282,8 @@ def formsemestre_bulletinetud(
|
||||
):
|
||||
if not formsemestre_id:
|
||||
flask.abort(404, "argument manquant: formsemestre_id")
|
||||
if not isinstance(formsemestre_id, int):
|
||||
raise ScoInvalidIdType("formsemestre_id must be an integer !")
|
||||
formsemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
if formsemestre.formation.is_apc() and format != "oldjson":
|
||||
if etudid:
|
||||
@ -744,6 +741,10 @@ def XMLgetFormsemestres(etape_apo=None, formsemestre_id=None):
|
||||
DEPRECATED: use formsemestre_list()
|
||||
"""
|
||||
current_app.logger.debug("Warning: calling deprecated XMLgetFormsemestres")
|
||||
if not formsemestre_id:
|
||||
return flask.abort(404, "argument manquant: formsemestre_id")
|
||||
if not isinstance(formsemestre_id, int):
|
||||
return flask.abort(404, "formsemestre_id must be an integer !")
|
||||
args = {}
|
||||
if etape_apo:
|
||||
args["etape_apo"] = etape_apo
|
||||
|
@ -424,7 +424,7 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
||||
"date_expiration",
|
||||
{
|
||||
"title": "Date d'expiration", # j/m/a
|
||||
"input_type": "date",
|
||||
"input_type": "datedmy",
|
||||
"explanation": "j/m/a, laisser vide si pas de limite",
|
||||
"size": 9,
|
||||
"allow_null": True,
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.1.22"
|
||||
SCOVERSION = "9.1.23"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user