CAS: ajout option pour utiliser par défaut le même uid ScoDoc et CAS + cosmetic formulaires

This commit is contained in:
Emmanuel Viennet 2024-09-15 16:50:25 +02:00
parent c38b8aa297
commit 9ae2181904
10 changed files with 327 additions and 250 deletions

View File

@ -355,6 +355,9 @@ class User(UserMixin, ScoDocModel):
super().from_dict(data, excluded={"user_name", "roles_string", "roles"})
if ScoDocSiteConfig.cas_uid_use_scodoc():
self.cas_id = self.user_name
else:
# Set cas_id using regexp if configured:
exp = ScoDocSiteConfig.get("cas_uid_from_mail_regexp")
if exp and self.email_institutionnel:

View File

@ -98,6 +98,15 @@ class ConfigCASForm(FlaskForm):
validators=[Optional(), check_cas_uid_from_mail_regexp],
)
cas_uid_use_scodoc = BooleanField(
"Utiliser l'identifiant ScoDoc comme identifiant CAS",
description="""Si coché, l'identifiant ScoDoc sera utilisé comme identifiant CAS,
sans transformation. Cette option est utile si les identifiants ScoDoc sont déjà
des identifiants CAS.
Dans ce cas, l'adresse mail (réglage ci-dessus) n'est pas utilisée.
""",
)
cas_edt_id_from_xml_regexp = StringField(
label="Optionnel: expression pour extraire l'identifiant edt",
description="""regexp python appliquée à la réponse XML du serveur CAS pour

View File

@ -105,6 +105,7 @@ class ScoDocSiteConfig(db.Model):
"cas_validate_route": str,
"cas_attribute_id": str,
"cas_uid_from_mail_regexp": str,
"cas_uid_use_scodoc": bool,
"cas_edt_id_from_xml_regexp": str,
# Assiduité
"morning_time": str,
@ -239,6 +240,12 @@ class ScoDocSiteConfig(db.Model):
cfg = ScoDocSiteConfig.query.filter_by(name="cas_force").first()
return cfg is not None and cfg.value
@classmethod
def cas_uid_use_scodoc(cls) -> bool:
"""True si cas_uid_use_scodoc"""
cfg = ScoDocSiteConfig.query.filter_by(name="cas_uid_use_scodoc").first()
return cfg is not None and cfg.value
@classmethod
def is_entreprises_enabled(cls) -> bool:
"""True si on doit activer le module entreprise"""
@ -404,7 +411,7 @@ class ScoDocSiteConfig(db.Model):
@classmethod
def extract_cas_id(cls, email_addr: str) -> str | None:
"Extract cas_id from maill, using regexp in config. None if not possible."
"Extract cas_id from mail, using regexp in config. None if not possible."
exp = cls.get("cas_uid_from_mail_regexp")
if not exp or not email_addr:
return None

View File

@ -1246,7 +1246,8 @@ a.discretelink:hover {
text-align: center;
}
.help {
.help,
.help-block {
max-width: var(--sco-content-max-width);
font-style: italic;
}
@ -1260,6 +1261,10 @@ a.discretelink:hover {
color: red;
}
div.help-block {
margin-bottom: 16px;
}
div.sco_box,
div.sco_help {
margin-top: 12px;
@ -4919,7 +4924,6 @@ table.formation_table_recap td.heures_tp {
}
div.cas_settings {
margin-left: -15px;
margin-bottom: 8px;
border: 1px dashed rgb(191, 34, 191);
background-color: #feb4e54f;

View File

@ -430,11 +430,21 @@ textarea {
color: #333;
}
form.form div.checkbox {
margin-top: 6px;
margin-bottom: 6px;
}
div.form-group {
margin-top: 16px;
margin-bottom: 6px;
}
.form-group input,
.form-control {
width: 100%;
padding: 10px;
margin-bottom: 16px;
margin-bottom: 4px;
border: 1px solid #ced4da;
border-radius: 4px;
font-size: 16px;

View File

@ -4,7 +4,7 @@
{% block app_content %}
<h1>Chargement des configurations CAS des utilisateurs</h1>
<div style="max-width: 800px;">
<div class="scobox help explanation">
<p style="color: red">A utiliser pour modifier le paramétrage CAS de
<b>comptes utilisateurs existants</b>
</p>
@ -32,21 +32,26 @@
<li style="margin-bottom:32px;">Revenez sur cette page et chargez le fichier dans ScoDoc.
</li>
</ol>
</div>
<div class="scobox">
<div class="scobox-title">Étape 1: exporter fichier Excel à charger</div>
<ul>
<li><b>Étape 1: </b><a class="stdlink" href="{{
<li><a class="stdlink" href="{{
url_for('auth.cas_users_generate_excel_sample')
}}">Obtenir la feuille excel à remplir</a>,
avec la liste complète des utilisateurs.
</li>
<li style="margin-top: 16px;"><b>Étape 2:</b>
</ul>
</div>
<div class="scobox">
<div class="scobox-title">Étape 2: charger le fichier Excel modifié</div>
<div class="row">
<div class="col-md-8">
{{ wtf.quick_form(form) }}
</div>
</div>
</li>
</ul>
</div>
{% endblock %}

View File

@ -1,6 +1,14 @@
{% extends "base.j2" %}
{% import 'wtf.j2' as wtf %}
{% block styles %}
{{super()}}
<style>
div.checkbox label { font-weight: normal; }
</style>
{% endblock %}
{% block app_content %}
<h1>Configuration du Service d'Authentification Central (CAS)</h1>
@ -18,14 +26,33 @@
{{ wtf.form_field(form.cas_enable) }}
{{ wtf.form_field(form.cas_force) }}
{{ wtf.form_field(form.cas_allow_for_new_users) }}
<div class="scobox">
<div class="scobox-title">Routes CAS</div>
{{ wtf.form_field(form.cas_server) }}
{{ wtf.form_field(form.cas_login_route) }}
{{ wtf.form_field(form.cas_logout_route) }}
{{ wtf.form_field(form.cas_validate_route) }}
</div>
<div class="scobox">
{{ wtf.form_field(form.cas_attribute_id) }}
</div>
<div class="scobox">
<div class="scobox-title">Identifiant utilisateur CAS</div>
<div class="help explanation">
Ces paramètres sont utilisés pour déduire
l'identifiant CAS des utilisateurs ScoDoc au moment de la création ou modification
de comptes utilisateurs. Pour modifier les comptes existants en masse, il peut être
pratique de passer par un
<a class="stdlink" href="{{ url_for('auth.cas_users_import_config') }}">export/import excel</a>.
</div>
{{ wtf.form_field(form.cas_uid_from_mail_regexp) }}
{{ wtf.form_field(form.cas_uid_use_scodoc) }}
</div>
<div class="scobox">
{{ wtf.form_field(form.cas_edt_id_from_xml_regexp) }}
<div class="cas_settings">
</div>
<div class="scobox cas_settings">
<div class="scobox-title">Certificat serveur CAS</div>
{{ wtf.form_field(form.cas_ssl_verify) }}
{{ wtf.form_field(form.cas_ssl_certificate_file) }}
<div class="cas_etat_certif_ssl">Certificat SSL

View File

@ -43,6 +43,9 @@ the necessary fix for required=False attributes, but will also not set the requi
<div class="checkbox">
<label>
{{field()|safe}} {{field.label.text|safe}}
{%- if field.description %}
<div class="help-block">{{field.description|safe}}</div>
{%- endif %}
</label>
</div>
{% endcall %}
@ -108,12 +111,12 @@ the necessary fix for required=False attributes, but will also not set the requi
{%- if field.errors %}
{%- for error in field.errors %}
{% call _hz_form_wrap(horizontal_columns, form_type, required=required) %}
<p class="help-block">{{error}}</p>
<div class="help-block">{{error}}</div>
{% endcall %}
{%- endfor %}
{%- elif field.description -%}
{% call _hz_form_wrap(horizontal_columns, form_type, required=required) %}
<p class="help-block">{{field.description|safe}}</p>
<div class="help-block">{{field.description|safe}}</div>
{% endcall %}
{%- endif %}
{%- else -%}
@ -126,10 +129,10 @@ the necessary fix for required=False attributes, but will also not set the requi
{%- if field.errors %}
{%- for error in field.errors %}
<p class="help-block">{{error}}</p>
<div class="help-block">{{error}}</div>
{%- endfor %}
{%- elif field.description -%}
<p class="help-block">{{field.description|safe}}</p>
<div class="help-block">{{field.description|safe}}</div>
{%- endif %}
{%- endif %}
</div>

View File

@ -296,6 +296,11 @@ def config_cas():
"cas_uid_from_mail_regexp", form.data["cas_uid_from_mail_regexp"]
):
flash("Expression extraction identifiant CAS enregistrée")
if ScoDocSiteConfig.set("cas_uid_use_scodoc", form.data["cas_uid_use_scodoc"]):
if form.data["cas_uid_use_scodoc"]:
flash("Utilisation de l'identifiant ScoDoc comme identifiant CAS")
else:
flash("N'utilise PAS l'identifiant ScoDoc pour le CAS")
if ScoDocSiteConfig.set(
"cas_edt_id_from_xml_regexp", form.data["cas_edt_id_from_xml_regexp"]
):
@ -313,7 +318,7 @@ def config_cas():
set_cas_configuration()
return redirect(url_for("scodoc.configuration"))
elif request.method == "GET":
if request.method == "GET":
form.cas_enable.data = ScoDocSiteConfig.get("cas_enable")
form.cas_force.data = ScoDocSiteConfig.get("cas_force")
form.cas_allow_for_new_users.data = ScoDocSiteConfig.get(
@ -327,6 +332,7 @@ def config_cas():
form.cas_uid_from_mail_regexp.data = ScoDocSiteConfig.get(
"cas_uid_from_mail_regexp"
)
form.cas_uid_use_scodoc.data = ScoDocSiteConfig.get("cas_uid_use_scodoc")
form.cas_edt_id_from_xml_regexp.data = ScoDocSiteConfig.get(
"cas_edt_id_from_xml_regexp"
)

View File

@ -404,10 +404,14 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
"input_type": "text",
"explanation": "id du compte utilisateur sur le CAS de l'établissement "
+ (
"<b>pa défaut identique à l'identifiant ScoDoc</b> "
if ScoDocSiteConfig.get("cas_uid_use_scodoc")
else (
"(<b>sera déduit de son e-mail institutionnel</b>) "
if ScoDocSiteConfig.get("cas_uid_from_mail_regexp")
else ""
)
)
+ (
"(service CAS activé)"
if cas_enabled
@ -537,7 +541,8 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
"d",
{
"input_type": "separator",
"title": f"L'utilisateur sera créé dans le département {auth_dept or 'aucun'}",
"title": f"""L'utilisateur sera créé dans le département {
auth_dept or 'aucun'}""",
},
)
)
@ -606,9 +611,9 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
content="\n".join(H) + "\n" + tf[1],
javascripts=["js/user_form.js"],
)
elif tf[0] == -1:
if tf[0] == -1:
return flask.redirect(url_for("users.index_html", scodoc_dept=g.scodoc_dept))
else:
vals = tf[2]
roles = set(vals["roles"]).intersection(editable_roles_strings)
if not current_user.is_administrator():
@ -798,9 +803,7 @@ def create_user_form(user_name=None, edit=0, all_roles=True):
if vals["dept"] not in selectable_dept_acronyms:
raise ScoValueError("département invalide")
# ok, go
log(
f"""sco_users: new_user {vals["user_name"]} by {current_user.user_name}"""
)
log(f"""sco_users: new_user {vals["user_name"]} by {current_user.user_name}""")
the_user = User(user_name=user_name)
the_user.from_dict(vals, new_user=True)
db.session.add(the_user)