forked from ScoDoc/ScoDoc
User: modification sémantique réglages CAS, page de login. New pref.
This commit is contained in:
parent
f98fbd1443
commit
a6c162dac8
@ -105,13 +105,8 @@ def users_info_query():
|
||||
|
||||
def _is_allowed_user_edit(args: dict) -> tuple[bool, str]:
|
||||
"Vrai si on peut"
|
||||
if "cas_id" in args and not current_user.has_permission(
|
||||
Permission.UsersChangeCASId
|
||||
):
|
||||
return False, "non autorise a changer cas_id"
|
||||
|
||||
if not current_user.is_administrator():
|
||||
for field in ("cas_allow_login", "cas_allow_scodoc_login"):
|
||||
if not current_user.has_permission(Permission.UsersChangeCASId):
|
||||
for field in ("cas_id", "cas_allow_login", "cas_allow_scodoc_login"):
|
||||
if field in args:
|
||||
return False, f"non autorise a changer {field}"
|
||||
return True, ""
|
||||
|
@ -158,7 +158,7 @@ CAS_USER_INFO_COMMENTS = (
|
||||
autorise la connexion via CAS (optionnel, faux par défaut)
|
||||
""",
|
||||
"""cas_allow_scodoc_login
|
||||
autorise connexion via ScoDoc même si CAS activé (optionnel, vrai par défaut)
|
||||
autorise connexion via ScoDoc même si CAS forcé (optionnel, faux par défaut)
|
||||
""",
|
||||
"""email_institutionnel
|
||||
optionnel, le mail officiel de l'utilisateur.
|
||||
|
@ -93,7 +93,7 @@ class User(UserMixin, ScoDocModel):
|
||||
cas_allow_scodoc_login = db.Column(
|
||||
db.Boolean, default=False, server_default="false", nullable=False
|
||||
)
|
||||
"""Si CAS activé et cas_id renseigné, peut-on se logguer sur ScoDoc directement ?
|
||||
"""Si CAS activé et forcé, peut-on se logguer sur ScoDoc directement ?
|
||||
(le rôle ScoSuperAdmin peut toujours, mettre à True pour les utilisateur API)
|
||||
"""
|
||||
cas_last_login = db.Column(db.DateTime, nullable=True)
|
||||
@ -179,42 +179,31 @@ class User(UserMixin, ScoDocModel):
|
||||
raise ValueError("invalid user_id")
|
||||
return query.first_or_404() if not accept_none else query.first()
|
||||
|
||||
def can_login_using_cas(self, require_cas_id=False) -> bool:
|
||||
"""True si l'utilisateur peut se connecter via CAS.
|
||||
Attention: si le cas_id est extrait de l'adresse mail, il est au départ vide.
|
||||
L'argument require_cas_id indique si on le requiert ou pas.
|
||||
"""
|
||||
return (
|
||||
self.cas_allow_login
|
||||
and (self.cas_id or not require_cas_id)
|
||||
and ScoDocSiteConfig.is_cas_enabled()
|
||||
)
|
||||
|
||||
def can_login_using_scodoc(self) -> bool:
|
||||
"""True si l'utilisateur peut (essayer de) se connecter avec son compte local ScoDoc
|
||||
(si par ailleurs un mot de passe valide existe et que le compte est actif)
|
||||
|
||||
Toujours vrai pour le super-admin.
|
||||
Si CAS activé and cas_id renseigné, il faut cas_allow_scodoc_login.
|
||||
|
||||
Réglages possibles:
|
||||
- Global : cas_force CAS forcé pour tous sauf super-admin
|
||||
- Par utilisateur:
|
||||
- cas_allow_login : Peut-on se logguer via le CAS ?
|
||||
- cas_allow_scodoc_login : Si CAS activé, peut-on se logguer sur ScoDoc ?
|
||||
|
||||
Toujours vrai pour le super-admin ou si CAS non activé.
|
||||
Si CAS forcé, il faut cas_allow_scodoc_login.
|
||||
"""
|
||||
if self.is_administrator():
|
||||
return True # super admin ou autorisation individuelle
|
||||
cas_enabled = ScoDocSiteConfig.is_cas_enabled()
|
||||
if not cas_enabled:
|
||||
|
||||
if not ScoDocSiteConfig.is_cas_enabled():
|
||||
return True # CAS not enabled
|
||||
|
||||
if not self.cas_allow_scodoc_login:
|
||||
log(
|
||||
f"""auth: {self.user_name
|
||||
}: cas enabled, scodoc login not allowed"""
|
||||
)
|
||||
return False
|
||||
|
||||
if ScoDocSiteConfig.is_cas_forced() and self.cas_id and self.cas_allow_login:
|
||||
log(
|
||||
f"""auth: {self.user_name
|
||||
} (cas_id='{
|
||||
self.cas_id}'): cas forced and cas_id set: scodoc login not allowed"""
|
||||
)
|
||||
return False
|
||||
|
||||
return True
|
||||
return self.cas_allow_scodoc_login or not ScoDocSiteConfig.is_cas_forced()
|
||||
|
||||
def set_password(self, password: str):
|
||||
"Set password"
|
||||
|
@ -36,7 +36,7 @@ def _login_form():
|
||||
form = LoginForm()
|
||||
if form.validate_on_submit():
|
||||
# note: ceci est la première requête SQL déclenchée par un utilisateur arrivant
|
||||
user = (
|
||||
user: User = (
|
||||
User.query.filter_by(user_name=form.user_name.data).first()
|
||||
if is_valid_user_name(form.user_name.data)
|
||||
else None
|
||||
@ -51,7 +51,7 @@ def _login_form():
|
||||
|
||||
current_app.logger.info("login: success (%s)", form.user_name.data)
|
||||
|
||||
if user.passwd_must_be_changed:
|
||||
if user.passwd_must_be_changed and user.can_login_using_scodoc():
|
||||
# Mot de passe à changer à la première connexion
|
||||
dept = user.dept or getattr(g, "scodoc_dept", None)
|
||||
if not dept:
|
||||
@ -87,8 +87,10 @@ def login():
|
||||
if current_user.is_authenticated:
|
||||
return redirect(url_for("scodoc.index"))
|
||||
|
||||
if ScoDocSiteConfig.is_cas_forced():
|
||||
current_app.logger.info("login: forcing CAS")
|
||||
if ScoDocSiteConfig.is_cas_forced() and ScoDocSiteConfig.get(
|
||||
"cas_login_redirect", default=True
|
||||
):
|
||||
current_app.logger.info("login: redirecting to CAS login")
|
||||
return redirect(url_for("cas.login"))
|
||||
|
||||
return _login_form()
|
||||
|
@ -58,6 +58,10 @@ class ConfigCASForm(FlaskForm):
|
||||
cas_allow_for_new_users = BooleanField(
|
||||
"Par défaut, autoriser le CAS aux nouveaux utilisateurs"
|
||||
)
|
||||
cas_login_redirect = BooleanField(
|
||||
"Si le CAS est forcé, redirige immédiatement la page de login vers le CAS",
|
||||
default=True,
|
||||
)
|
||||
|
||||
cas_server = StringField(
|
||||
label="URL du serveur CAS",
|
||||
|
@ -99,6 +99,9 @@ class ScoDocSiteConfig(models.ScoDocModel):
|
||||
"user_require_email_institutionnel": bool,
|
||||
# CAS
|
||||
"cas_enable": bool,
|
||||
"cas_force": bool,
|
||||
"cas_allow_for_new_users": bool,
|
||||
"cas_login_redirect": bool,
|
||||
"cas_server": str,
|
||||
"cas_login_route": str,
|
||||
"cas_logout_route": str,
|
||||
|
@ -653,11 +653,11 @@ class FormSemestre(models.ScoDocModel):
|
||||
Si le semestre est verrouillé, faux sauf si allow_locked.
|
||||
"""
|
||||
user = user or current_user
|
||||
if user.passwd_must_be_changed or not user.has_permission(
|
||||
Permission.EditFormSemestre
|
||||
): # pas chef de dept.
|
||||
if not user.has_permission(Permission.EditFormSemestre):
|
||||
# pas chef de dept.
|
||||
if not self.resp_can_edit or not self.est_responsable(user):
|
||||
return False
|
||||
# resp_can_edit et est_responsable
|
||||
return allow_locked or self.etat
|
||||
|
||||
def est_courant(self) -> bool:
|
||||
|
@ -62,7 +62,7 @@ _SCO_PERMISSIONS = (
|
||||
"RelationsEntrepExport",
|
||||
"Exporter les données de l'application relations entreprises",
|
||||
),
|
||||
(1 << 29, "UsersChangeCASId", "Paramétrer l'id CAS"),
|
||||
(1 << 29, "UsersChangeCASId", "Modifier les paramètres CAS des utilisateurs"),
|
||||
(1 << 30, "ViewEtudData", "Accéder aux données personnelles des étudiants"),
|
||||
#
|
||||
# XXX inutilisée ? (1 << 40, "EtudChangePhoto", "Modifier la photo d'un étudiant"),
|
||||
|
@ -323,31 +323,6 @@ nav li.logout a {
|
||||
color: rgb(255, 0, 0);
|
||||
}
|
||||
|
||||
div.user_info div {
|
||||
padding: 8px;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
div.user_info ul li {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
div.user_basics {
|
||||
border: 1px solid blue;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
div.user_info_admin {
|
||||
border: 1px solid red;
|
||||
background-color: #fdcaca;
|
||||
}
|
||||
|
||||
div.user_info div.permissions {
|
||||
border: 1px solid rgb(0, 0, 255);
|
||||
background-color: #dedefd;
|
||||
}
|
||||
|
||||
/* ----- page content ------ */
|
||||
|
||||
div.about-logo {
|
||||
|
@ -25,7 +25,7 @@
|
||||
<h1>Modification du compte ScoDoc <tt>{{form.user_name.data}}</tt></h1>
|
||||
<div class="help" style="margin-top: 32px; margin-bottom: 32px;">
|
||||
<p>Le mot de passe ScoDoc doit être suffisament complexe.
|
||||
Il n'a rien à voir avec celui de votre compte ENT (utilisé pour le service CAS).
|
||||
Il n'a rien à voir avec ceux des comptes utilisés par le service CAS (ENT).
|
||||
</p>
|
||||
</div>
|
||||
<form method="post">
|
||||
|
@ -29,7 +29,10 @@ div.small_form {
|
||||
{% endif %}
|
||||
|
||||
{% if is_cas_enabled %}
|
||||
<div class="cas_else">Sinon vous pouvez vous connecter avec votre compte ScoDoc:</div>
|
||||
<div class="cas_else">Sinon
|
||||
{%- if is_cas_forced -%}, si votre compte ScoDoc le permet, {% endif %}
|
||||
connectez-vous avec vos identifiants ScoDoc:
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row {{ 'small_form' if is_cas_enabled else ''}}">
|
||||
<div class="col-md-4">
|
||||
@ -38,12 +41,16 @@ div.small_form {
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 32px;">
|
||||
En cas d'oubli de votre mot de passe ScoDoc (indépendant de CAS)
|
||||
En cas d'oubli de votre mot de passe ScoDoc
|
||||
{% if is_cas_enabled %}(indépendant de CAS){% endif %},
|
||||
<a href="{{ url_for('auth.reset_password_request') }}">cliquez ici pour le réinitialiser</a>.
|
||||
</div>
|
||||
|
||||
|
||||
<p class="help" style="margin-top: 32px;">L'accès à ScoDoc est strictement réservé aux personnels de
|
||||
l'établissement. Les étudiants n'y ont pas accès. Pour toute information,
|
||||
contactez la personne responsable de votre établissement.</p>
|
||||
<p class="help" style="margin-top: 32px;">
|
||||
L'accès à ScoDoc est strictement réservé aux personnels de
|
||||
l'établissement. Les étudiants n'y ont pas accès. Pour toute information,
|
||||
contactez la personne responsable de votre établissement.
|
||||
</p>
|
||||
|
||||
{% endblock %}
|
||||
|
@ -2,52 +2,101 @@
|
||||
{% extends "base.j2" %}
|
||||
{% import 'wtf.j2' as wtf %}
|
||||
|
||||
{% block styles %}
|
||||
{{super()}}
|
||||
<style>
|
||||
|
||||
div.ubi div {
|
||||
|
||||
}
|
||||
div.user_info_admin {
|
||||
border: 1px solid red;
|
||||
background-color: #fdcaca;
|
||||
}
|
||||
|
||||
div.user_basics {
|
||||
border: 1px solid blue;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
div.user_info > div {
|
||||
padding: 8px;
|
||||
border-radius: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
div.user_info ul li {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
div.user_info div.permissions {
|
||||
border: 1px solid rgb(0, 0, 255);
|
||||
background-color: #dedefd;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
<div class="user_info">
|
||||
<h2>Utilisateur: {{user.user_name}} ({{'actif' if user.active else 'fermé'}})</h2>
|
||||
<div class="user_basics">
|
||||
<b>Login :</b> {{user.user_name}}
|
||||
<div><b>Login :</b> {{user.user_name}}
|
||||
{% if ScoDocSiteConfig.is_cas_enabled() %}
|
||||
(connexion via ce login ScoDoc
|
||||
{% if user.can_login_using_scodoc() %}autorisée{% else %}<span class="fontred">interdite</span>
|
||||
{% endif %})
|
||||
{% endif -%}
|
||||
<br>
|
||||
<b>CAS id:</b> {{user.cas_id or "(aucun)"}}
|
||||
</div>
|
||||
<div><b>CAS id:</b> {{user.cas_id or "(aucun)"}}
|
||||
{% if ScoDocSiteConfig.is_cas_enabled() %}
|
||||
(CAS {{'autorisé' if user.cas_allow_login else 'interdit'}} pour cet utilisateur)
|
||||
(CAS {{'autorisé' if user.can_login_using_cas() else 'interdit'}} pour cet utilisateur)
|
||||
{% if user.can_login_using_scodoc() %}
|
||||
(connexion sans CAS autorisée)
|
||||
{% endif %}
|
||||
{% if user.cas_allow_login and not user.cas_id %}
|
||||
(pas encore d'identifiant CAS)
|
||||
{% endif %}
|
||||
<br>
|
||||
<b>Nom :</b> {{user.nom or ""}}<br>
|
||||
<b>Prénom :</b> {{user.prenom or ""}}<br>
|
||||
{% endif %}
|
||||
{% if not user.can_login_using_scodoc() and not user.can_login_using_cas() %}
|
||||
<div class="warning">cet utilisateur ne peut se connecter ni via ScoDoc ni via CAS</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div><b>Nom :</b> {{user.nom or ""}}</div>
|
||||
<div><b>Prénom :</b> {{user.prenom or ""}}</div>
|
||||
<div>
|
||||
{% if user.passwd_must_be_changed %}
|
||||
<div style="color:white; background-color: red; padding:8px; margin-top: 4px; width: fit-content;">mot de passe à changer</div>
|
||||
<div style="color:white; background-color: red; padding:8px; margin-top: 4px; width: fit-content;">mot de passe ScoDoc à changer</div>
|
||||
{% endif %}
|
||||
<b>Mail :</b> {{user.email}}<br>
|
||||
<b>Mail institutionnel:</b> {{user.email_institutionnel or ""}}<br>
|
||||
<b>Identifiant EDT:</b> {{user.edt_id or ""}}<br>
|
||||
<b>Rôles :</b> {{user.get_roles_string()}}<br>
|
||||
<b>Dept :</b> {{user.dept or ""}}<br>
|
||||
</div>
|
||||
<div><b>Mail :</b> {{user.email}}</div>
|
||||
<div><b>Mail institutionnel:</b> {{user.email_institutionnel or ""}}</div>
|
||||
<div><b>Identifiant EDT:</b> {{user.edt_id or ""}}</div>
|
||||
<div><b>Rôles :</b> {{user.get_roles_string()}}</div>
|
||||
<div><b>Dept :</b> {{user.dept or ""}}</div>
|
||||
<div>
|
||||
{% if user.passwd_temp or user.password_scodoc7 %}
|
||||
<b class="fontred">⚠️ mot de passe invalide (compte ancien non migré à réactiver ou à fermer)</b><br>
|
||||
<b class="fontred">⚠️ mot de passe invalide (compte ancien non migré à réactiver ou à fermer)</b>
|
||||
{% endif %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% if current_user.is_administrator() %}
|
||||
<div class="user_info_admin">
|
||||
<b>Dernière vue :</b> {{user.last_seen.strftime(scu.DATEATIME_FMT) if user.last_seen else "-"}}<br>
|
||||
<b>Dernière connexion CAS :</b> {{user.cas_last_login.strftime(scu.DATEATIME_FMT) if user.cas_last_login else "-"}}<br>
|
||||
<div class="ubi user_info_admin">
|
||||
<div>
|
||||
<b>Dernière vue :</b> {{user.last_seen.strftime(scu.DATEATIME_FMT) if user.last_seen else "-"}}</div><div>
|
||||
<b>Dernière connexion CAS :</b> {{user.cas_last_login.strftime(scu.DATEATIME_FMT) if user.cas_last_login else "-"}}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="user_basics">
|
||||
<div class="ubi user_basics">
|
||||
<div>
|
||||
<b>Dernière modif mot de passe:</b>
|
||||
{{user.date_modif_passwd.strftime(scu.DATEATIME_FMT) if user.date_modif_passwd else ""}}<br>
|
||||
{{user.date_modif_passwd.strftime(scu.DATEATIME_FMT) if user.date_modif_passwd else ""}}
|
||||
</div>
|
||||
<div>
|
||||
<b>Date d'expiration:</b>
|
||||
{{user.date_expiration.strftime(scu.DATE_FMT) if user.date_expiration else "(sans limite)"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -79,6 +128,10 @@
|
||||
}}">{{"désactiver" if user.active else "activer"}} ce compte</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li><a class="stdlink" href="
|
||||
{{url_for('users.index_html', scodoc_dept=g.scodoc_dept)}}
|
||||
">retour à la liste de tous les utilisateurs</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@ -105,7 +158,7 @@
|
||||
|
||||
{# Liste des permissions #}
|
||||
<div class="permissions">
|
||||
<p><b>Permissions de cet utilisateur dans le département {{dept}}:</b></p>
|
||||
<b>Permissions de l'utilisateur {{user.user_name}} dans le département {{dept}}</b>
|
||||
<ul>
|
||||
{% for p in Permission.description %}
|
||||
<li>{{Permission.description[p]}} :
|
||||
|
@ -26,6 +26,7 @@
|
||||
{{ wtf.form_field(form.cas_enable) }}
|
||||
{{ wtf.form_field(form.cas_force) }}
|
||||
{{ wtf.form_field(form.cas_allow_for_new_users) }}
|
||||
{{ wtf.form_field(form.cas_login_redirect) }}
|
||||
<div class="scobox">
|
||||
<div class="scobox-title">Routes CAS</div>
|
||||
{{ wtf.form_field(form.cas_server) }}
|
||||
|
@ -282,6 +282,11 @@ def config_cas():
|
||||
f"""CAS {'' if form.data['cas_allow_for_new_users'] else 'non'
|
||||
} autorisé par défaut aux nouveaux"""
|
||||
)
|
||||
if ScoDocSiteConfig.set("cas_login_redirect", form.data["cas_login_redirect"]):
|
||||
flash(
|
||||
f"""Page login {'' if form.data['cas_login_redirect'] else 'non'
|
||||
} redirigée si CAS forcé"""
|
||||
)
|
||||
if ScoDocSiteConfig.set("cas_server", form.data["cas_server"]):
|
||||
flash("URL du serveur CAS enregistrée")
|
||||
if ScoDocSiteConfig.set("cas_login_route", form.data["cas_login_route"]):
|
||||
@ -324,6 +329,7 @@ def config_cas():
|
||||
form.cas_allow_for_new_users.data = ScoDocSiteConfig.get(
|
||||
"cas_allow_for_new_users"
|
||||
)
|
||||
form.cas_login_redirect.data = ScoDocSiteConfig.get("cas_login_redirect")
|
||||
form.cas_server.data = ScoDocSiteConfig.get("cas_server")
|
||||
form.cas_login_route.data = ScoDocSiteConfig.get("cas_login_route")
|
||||
form.cas_logout_route.data = ScoDocSiteConfig.get("cas_logout_route")
|
||||
|
@ -406,6 +406,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
)
|
||||
]
|
||||
cas_enabled = ScoDocSiteConfig.is_cas_enabled()
|
||||
can_edit_cas = current_user.has_permission(Permission.UsersChangeCASId)
|
||||
if edit:
|
||||
cas_allow_login_default = the_user.cas_allow_login
|
||||
else:
|
||||
@ -453,8 +454,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
),
|
||||
"size": 36,
|
||||
"allow_null": True,
|
||||
"readonly": not cas_enabled
|
||||
or not current_user.has_permission(Permission.UsersChangeCASId),
|
||||
"readonly": not cas_enabled or not can_edit_cas,
|
||||
},
|
||||
),
|
||||
(
|
||||
@ -462,9 +462,8 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
{
|
||||
"title": "Autorise connexion via CAS",
|
||||
"input_type": "boolcheckbox",
|
||||
"explanation": """ si CAS est activé.
|
||||
Seul le super-administrateur peut changer ce réglage.""",
|
||||
"enabled": current_user.is_administrator(),
|
||||
"explanation": """ si CAS est activé.""",
|
||||
"enabled": can_edit_cas,
|
||||
"default": cas_allow_login_default,
|
||||
},
|
||||
),
|
||||
@ -473,9 +472,8 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
{
|
||||
"title": "Autorise connexion via ScoDoc",
|
||||
"input_type": "boolcheckbox",
|
||||
"explanation": """ même si CAS est activé et cas_id renseigné.
|
||||
Seul le super-administrateur peut changer ce réglage""",
|
||||
"enabled": current_user.is_administrator(),
|
||||
"explanation": """ même si CAS est forcé.""",
|
||||
"enabled": can_edit_cas,
|
||||
},
|
||||
),
|
||||
(
|
||||
@ -663,7 +661,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
if "obusfacted_u_ser_nam_" in initvalues:
|
||||
initvalues["user_name"] = initvalues["obusfacted_u_ser_nam_"]
|
||||
roles = set(vals["roles"]).intersection(editable_roles_strings)
|
||||
if not current_user.is_administrator():
|
||||
if not can_edit_cas:
|
||||
# empeche modification des paramètres CAS
|
||||
if "cas_allow_login" in vals:
|
||||
vals["cas_allow_login"] = cas_allow_login_default
|
||||
@ -672,9 +670,8 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
|
||||
vals.pop("cas_allow_scodoc_login", None)
|
||||
else:
|
||||
vals["cas_allow_scodoc_login"] = the_user.cas_allow_scodoc_login
|
||||
|
||||
if not current_user.has_permission(Permission.UsersChangeCASId):
|
||||
vals.pop("cas_id", None)
|
||||
|
||||
if "edit" in vals:
|
||||
edit = int(vals["edit"])
|
||||
else:
|
||||
|
@ -3,11 +3,21 @@
|
||||
|
||||
"Infos sur version ScoDoc"
|
||||
|
||||
SCOVERSION = "9.7.56"
|
||||
SCOVERSION = "9.7.57"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
SCONEWS = """
|
||||
|
||||
<h4>Année 2024-2025</h4>
|
||||
<ul>
|
||||
|
||||
<li>ScoDoc 9.7</li>
|
||||
<ul>
|
||||
<li>Amélioration gestion utilisateurs et CAS</li>
|
||||
<li>TODO</li>
|
||||
</ul>
|
||||
|
||||
<h4>Année 2023-2024</h4>
|
||||
<ul>
|
||||
|
||||
|
@ -126,7 +126,7 @@ def test_create_delete(test_client):
|
||||
|
||||
|
||||
def test_edit(test_client):
|
||||
"test edition object utlisateur"
|
||||
"test edition object utilisateur"
|
||||
args = {
|
||||
"prenom": "No Totoro",
|
||||
"edt_id": "totorito",
|
||||
|
Loading…
x
Reference in New Issue
Block a user