Améliorer page infos utilisateurs

This commit is contained in:
Emmanuel Viennet 2021-10-17 11:19:01 +02:00
parent c96b114b08
commit a909a307c0
10 changed files with 147 additions and 123 deletions

View File

@ -43,8 +43,11 @@ class UserCreationForm(FlaskForm):
class ResetPasswordRequestForm(FlaskForm): class ResetPasswordRequestForm(FlaskForm):
email = StringField(_l("Email"), validators=[DataRequired(), Email()]) email = StringField(
submit = SubmitField(_l("Valider ce mot de passe")) _l("Adresse email associée à votre compte ScoDoc:"),
validators=[DataRequired(), Email()],
)
submit = SubmitField(_l("Envoyer"))
class ResetPasswordForm(FlaskForm): class ResetPasswordForm(FlaskForm):

View File

@ -98,7 +98,9 @@ def reset_password_request():
current_app.logger.info( current_app.logger.info(
"reset_password_request: for unkown user '{}'".format(form.email.data) "reset_password_request: for unkown user '{}'".format(form.email.data)
) )
flash(_("Voir les instructions envoyées par mail")) flash(
_("Voir les instructions envoyées par mail (pensez à regarder vos spams)")
)
return redirect(url_for("auth.login")) return redirect(url_for("auth.login"))
return render_template( return render_template(
"auth/reset_password_request.html", title=_("Reset Password"), form=form "auth/reset_password_request.html", title=_("Reset Password"), form=form

View File

@ -32,6 +32,7 @@
import re import re
from flask import url_for, g, request from flask import url_for, g, request
from flask.templating import render_template
from flask_login import current_user from flask_login import current_user
@ -271,102 +272,6 @@ def user_info(user_name_or_id=None, user=None):
return info return info
def user_info_page(user_name=None):
"""Display page of info about given user.
If user_name not specified, user current_user
"""
from app.scodoc.sco_permissions_check import can_handle_passwd
# peut on divulguer ces infos ?
if not can_handle_passwd(current_user, allow_admindepts=True):
raise AccessDenied("Vous n'avez pas la permission de voir cette page")
dept = g.scodoc_dept
if not user_name:
user = current_user
else:
user = User.query.filter_by(user_name=user_name).first()
if not user:
raise ScoValueError("invalid user_name")
H = [
html_sco_header.sco_header(
page_title="Utilisateur %s" % user.user_name,
)
]
F = html_sco_header.sco_footer()
H.append("<h2>Utilisateur: %s" % user.user_name)
info = user.to_dict()
if info:
H.append(" (%(status_txt)s)" % info)
H.append("</h2>")
if not info:
H.append(
"<p>L' utilisateur '%s' n'est pas défini dans ce module.</p>" % user_name
)
if user.has_permission(Permission.ScoEditAllNotes, dept):
H.append("<p>(il peut modifier toutes les notes de %s)</p>" % dept)
if user.has_permission(Permission.ScoEditAllEvals, dept):
H.append("<p>(il peut modifier toutes les évaluations de %s)</p>" % dept)
if user.has_permission(Permission.ScoImplement, dept):
H.append("<p>(il peut creer des formations en %s)</p>" % dept)
else:
H.append(
"""<p>
<b>Login :</b> %(user_name)s<br/>
<b>Nom :</b> %(nom)s<br/>
<b>Prénom :</b> %(prenom)s<br/>
<b>Mail :</b> %(email)s<br/>
<b>Roles :</b> %(roles_string)s<br/>
<b>Dept :</b> %(dept)s<br/>
<b>Dernière modif mot de passe:</b> %(date_modif_passwd)s<br/>
<b>Date d'expiration:</b> %(date_expiration)s
<p><ul>
<li><a class="stdlink" href="form_change_password?user_name=%(user_name)s">changer le mot de passe</a></li>"""
% info
)
if current_user.has_permission(Permission.ScoUsersAdmin, dept):
H.append(
f"""
<li><a class="stdlink" href="{url_for('users.create_user_form', scodoc_dept=g.scodoc_dept,
user_name=user.user_name, edit=1)}">modifier ce compte</a>
</li>
<li><a class="stdlink" href="{url_for('users.toggle_active_user', scodoc_dept=g.scodoc_dept,
user_name=user.user_name)
}">{"désactiver" if user.active else "activer"} ce compte</a>
</li>
"""
% info
)
H.append("</ul>")
if current_user.user_name == user_name:
H.append(
'<p><b>Se déconnecter: <a class="stdlink" href="%s">logout</a></b></p>'
% url_for("auth.logout")
)
# Liste des permissions
H.append(
'<div class="permissions"><p>Permissions de cet utilisateur dans le département %s:</p><ul>'
% dept
)
for p in Permission.description:
perm = getattr(Permission, p)
if user.has_permission(perm, dept):
b = "oui"
else:
b = "non"
H.append("<li>%s : %s</li>" % (Permission.description[p], b))
H.append("</ul></div>")
if current_user.has_permission(Permission.ScoUsersAdmin, dept):
H.append(
'<p><a class="stdlink" href="%s">Liste de tous les utilisateurs</a></p>'
% url_for("users.index_html", scodoc_dept=g.scodoc_dept)
)
return "\n".join(H) + F
def check_modif_user( def check_modif_user(
edit, edit,
enforce_optionals=False, enforce_optionals=False,

View File

@ -17,21 +17,27 @@
{% endmacro %} {% endmacro %}
{% block app_content %} {% block app_content %}
<h1>Changez vos données personnelles</h1> <h1>Modification du compte ScoDoc <tt>{{form.user_name.data}}</tt></h1>
<p>Identifiez vous avez votre mot de passe actuel</p> <div class="help">
<p>Vous pouvez changer votre mot de passe (laisez les champs vides sinon)</p> <p>Identifiez-vous avez votre mot de passe actuel</p>
<p>et/ou votre adresse email.</p> <p>Vous pouvez changer le mot de passe et/ou l'adresse email.</p>
<p>Les champs vides ne seront pas changés.</p>
</div>
<form method=post> <form method=post>
{{ form.user_name }} {{ form.user_name }}
{{ form.csrf_token }} {{ form.csrf_token }}
<table class="tf"><tbody> <table class="tf"><tbody>
{{ render_field(form.old_password, size=14, style="padding:1px;") }} {{ render_field(form.old_password, size=14,
{{ render_field(form.new_password, size=14, style="padding:1px;") }} style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
{{ render_field(form.bis_password, size=14, style="padding:1px;") }} {{ render_field(form.new_password, size=14,
{{ render_field(form.email, size=40, style="padding:1px;") }} style="padding:1px; margin-left: 1em; margin-top: 12px;") }}
{{ render_field(form.submit) }} {{ render_field(form.bis_password, size=14,
style="padding:1px; margin-left: 1em; margin-top: 4px;") }}
{{ render_field(form.email, size=40,
style="padding:1px; margin-top: 12px;margin-bottom: 16px; margin-left: 1em;") }}
</tbody></table> </tbody></table>
<input type="submit" value="Valider">
<input type="submit" name="cancel" value="Annuler" style="margin-left: 1em;>
</form> </form>
{#<div class="row" style="margin-top: 30px;">#} {#<div class="row" style="margin-top: 30px;">#}

View File

@ -2,7 +2,7 @@
{% import 'bootstrap/wtf.html' as wtf %} {% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %} {% block app_content %}
<h1>Reset Password</h1> <h1>Demande d'un nouveau mot de passe</h1>
<div class="row"> <div class="row">
<div class="col-md-4"> <div class="col-md-4">
{{ wtf.quick_form(form) }} {{ wtf.quick_form(form) }}

View File

@ -0,0 +1,67 @@
{% extends "base.html" %}
{% import 'bootstrap/wtf.html' as wtf %}
{% block app_content %}
<h2>Utilisateur: {{user.user_name}} ({{'actif' if user.active else 'fermé'}})</h2>
<p>
<b>Login :</b> {{user.user_name}}<br/>
<b>Nom :</b> {{user.nom or ""}}<br/>
<b>Prénom :</b> {{user.prenom or ""}}<br/>
<b>Mail :</b> {{user.email}}<br/>
<b>Roles :</b> {{user.get_roles_string()}}<br/>
<b>Dept :</b> {{user.dept or ""}}<br/>
<b>Dernière modif mot de passe:</b>
{{user.date_modif_passwd.isoformat() if user.date_modif_passwd else ""}}<br/>
<b>Date d'expiration:</b>
{{user.date_expiration.isoformat() if user.date_expiration else "(sans limite)"}}
<p>
<ul>
<li><a class="stdlink" href="{{
url_for( 'users.form_change_password',
scodoc_dept=g.scodoc_dept, user_name=user.user_name)
}}">modifier le mot de passe ou l'adresse mail</a>
</li>
{% if current_user.has_permission(Permission.ScoUsersAdmin, dept) %}
<li><a class="stdlink" href="{{
url_for('users.create_user_form', scodoc_dept=g.scodoc_dept,
user_name=user.user_name, edit=1)
}}">modifier ce compte</a>
</li>
<li><a class="stdlink" href="{{
url_for('users.toggle_active_user', scodoc_dept=g.scodoc_dept,
user_name=user.user_name)
}}">{{"désactiver" if user.active else "activer"}} ce compte</a>
</li>
{% endif %}
</ul>
{% if current_user.id == user.id %}
<p><b>Se déconnecter:
<a class="stdlink" href="{{url_for('auth.logout')}}">logout</a>
</b></p>
{% endif %}
{# Liste des permissions #}
<div class="permissions">
<p>Permissions de cet utilisateur dans le département {dept}:</p>
<ul>
{% for p in Permission.description %}
<li>{{Permission.description[p]}} :
{{
"oui" if user.has_permission(Permission.get_by_name(p), dept) else "non"
}}
</li>
{% endfor %}
</ul>
</div>
{% if current_user.has_permission(Permission.ScoUsersAdmin, dept) %}
<p><a class="stdlink" href="
{{url_for('users.index_html', scodoc_dept=g.scodoc_dept)}}
">Liste de tous les utilisateurs</a></p>
{% endif %}
{% endblock %}

View File

@ -22,12 +22,19 @@
</button> </button>
<a class="navbar-brand" href="{{ url_for('scodoc.index') }}">ScoDoc</a> <a class="navbar-brand" href="{{ url_for('scodoc.index') }}">ScoDoc</a>
</div> </div>
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
{% if current_user.is_administrator() %}
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li><a href="{{ url_for('scodoc.configuration') }}">configuration</a></li> {% if current_user.is_administrator() %}
</ul> <li><a href="{{ url_for('scodoc.configuration') }}">Configuration</a></li>
{% endif %} {% endif %}
{% if g.scodoc_dept %}
<li><a href="{{
url_for('scolar.index_html', scodoc_dept=g.scodoc_dept)
}}">Dept. {{ g.scodoc_dept }}</a></li>
{% endif %}
</ul>
<ul class="nav navbar-nav navbar-right"> <ul class="nav navbar-nav navbar-right">
{% if current_user.is_anonymous %} {% if current_user.is_anonymous %}
<li><a href="{{ url_for('auth.login') }}">connexion</a></li> <li><a href="{{ url_for('auth.login') }}">connexion</a></li>

View File

@ -5,7 +5,7 @@
cliquez sur ce lien cliquez sur ce lien
</a>. </a>.
</p> </p>
<p>Vous pouvez aussi copier ce lien dans votre navigateur Web::</p> <p>Vous pouvez aussi copier ce lien dans votre navigateur Web:</p>
<p>{{ url_for('auth.reset_password', token=token, _external=True) }}</p> <p>{{ url_for('auth.reset_password', token=token, _external=True) }}</p>
<p>Si vous n'avez pas demandé à réinitialiser votre mot de passe sur <p>Si vous n'avez pas demandé à réinitialiser votre mot de passe sur

View File

@ -46,7 +46,6 @@ from wtforms import HiddenField, PasswordField, StringField, SubmitField
from wtforms.validators import DataRequired, Email, ValidationError, EqualTo from wtforms.validators import DataRequired, Email, ValidationError, EqualTo
from app import db from app import db
from app.api.auth import verify_password
from app.auth.forms import DeactivateUserForm from app.auth.forms import DeactivateUserForm
from app.auth.models import Permission from app.auth.models import Permission
from app.auth.models import User from app.auth.models import User
@ -92,20 +91,21 @@ class ChangePasswordForm(FlaskForm):
], ],
) )
email = StringField(_l("Email"), validators=[DataRequired(), Email()]) email = StringField(_l("Email"), validators=[DataRequired(), Email()])
submit = SubmitField(_l("Modifier")) submit = SubmitField()
cancel = SubmitField("Annuler")
def validate_email(self, email): def validate_email(self, email):
user = User.query.filter_by(email=email.data).first() user = User.query.filter_by(email=email.data).first()
if user is not None and self.user_name.data != user.user_name: if user is not None and self.user_name.data != user.user_name:
raise ValidationError(_("Please choose a different email address.")) raise ValidationError(_("Adresse e-mail invalide"))
def validate_new_password(self, new_password): def validate_new_password(self, new_password):
if new_password.data != "" and not is_valid_password(new_password.data): if new_password.data != "" and not is_valid_password(new_password.data):
raise ValidationError(f"Mot de passe trop simple, recommencez") raise ValidationError(f"Mot de passe trop simple, recommencez")
def validate_old_password(self, old_password): def validate_old_password(self, old_password):
if not verify_password(self.user_name.data, old_password.data): if not current_user.check_password(old_password.data):
raise ValidationError("Ancien mot de passe incorrect, recommenccez") raise ValidationError("Mot de passe actuel incorrect, ré-essayez")
@bp.route("/") @bp.route("/")
@ -681,8 +681,31 @@ def import_users_form():
@scodoc @scodoc
@permission_required(Permission.ScoUsersView) @permission_required(Permission.ScoUsersView)
@scodoc7func @scodoc7func
def user_info_page(user_name): def user_info_page(user_name=None):
return sco_users.user_info_page(user_name=user_name) """Display page of info about given user.
If user_name not specified, user current_user
"""
from app.scodoc.sco_permissions_check import can_handle_passwd
# peut on divulguer ces infos ?
if not can_handle_passwd(current_user, allow_admindepts=True):
raise AccessDenied("Vous n'avez pas la permission de voir cette page")
dept = g.scodoc_dept
if not user_name:
user = current_user
else:
user = User.query.filter_by(user_name=user_name).first()
if not user:
raise ScoValueError("invalid user_name")
return render_template(
"auth/user_info_page.html",
user=user,
title=f"Utilisateur {user.user_name}",
Permission=Permission,
dept=dept,
)
@bp.route("/get_user_list_xml") @bp.route("/get_user_list_xml")
@ -736,6 +759,13 @@ def form_change_password(user_name=None):
] ]
) )
form = ChangePasswordForm(user_name=user.user_name, email=user.email) form = ChangePasswordForm(user_name=user.user_name, email=user.email)
destination = url_for(
"users.user_info_page",
scodoc_dept=g.scodoc_dept,
user_name=user_name,
)
if request.method == "POST" and form.cancel.data: # cancel button clicked
return redirect(destination)
if form.validate_on_submit(): if form.validate_on_submit():
messages = [] messages = []
if form.new_password.data != "": # change password if form.new_password.data != "": # change password
@ -746,7 +776,11 @@ def form_change_password(user_name=None):
messages.append("Adresse email modifiée") messages.append("Adresse email modifiée")
db.session.commit() db.session.commit()
flash("\n".join(messages)) flash("\n".join(messages))
return render_template("auth/change_password.html", form=form) return redirect(destination)
return render_template(
"auth/change_password.html", form=form, title="Modification compte ScoDoc"
)
@bp.route("/change_password", methods=["POST"]) @bp.route("/change_password", methods=["POST"])

View File

@ -1,7 +1,7 @@
# -*- mode: python -*- # -*- mode: python -*-
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
SCOVERSION = "9.0.53" SCOVERSION = "9.0.54"
SCONAME = "ScoDoc" SCONAME = "ScoDoc"