forked from ScoDoc/ScoDoc
début implémentation gestion utilisateurs
This commit is contained in:
parent
769671b0d4
commit
f991ffdca5
39
README.md
39
README.md
@ -51,9 +51,11 @@ Puis d'installer Flask comme suit:
|
|||||||
|
|
||||||
Installation:
|
Installation:
|
||||||
|
|
||||||
|
apt-get install libcrack2-dev
|
||||||
pip install flask
|
pip install flask
|
||||||
# et pas mal d'autres paquets
|
# et pas mal d'autres paquets
|
||||||
|
|
||||||
|
|
||||||
donc utiliser:
|
donc utiliser:
|
||||||
|
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
@ -62,6 +64,43 @@ pour régénerer ce fichier:
|
|||||||
|
|
||||||
pip freeze > requirements.txt
|
pip freeze > requirements.txt
|
||||||
|
|
||||||
|
## Bases de données
|
||||||
|
ScoDoc8 utilise les bases de département de ScoDoc7, mais une nouvelle base
|
||||||
|
utilisateurs nommée `SCO8USERS` (au lieu de `SCOUSERS`), qui est manipulée
|
||||||
|
via `sqlalchemy`.
|
||||||
|
|
||||||
|
### Configuration de la base utilisateurs
|
||||||
|
|
||||||
|
On va créer une base nommée `SCO8USERS`, appartenant à l'utilisateur (aka role) postgres `scodoc`.
|
||||||
|
Cet utilisateur sera créé ainsi sur le serveur linux::
|
||||||
|
|
||||||
|
su - postgres
|
||||||
|
createuser --no-createdb --no-createrole --pwprompt scodoc
|
||||||
|
|
||||||
|
Puis création de la base (en tant qu'utilisateur `postgres`):
|
||||||
|
|
||||||
|
createdb -O scodoc SCO8USERS
|
||||||
|
|
||||||
|
### Initialisation base par flask
|
||||||
|
|
||||||
|
En tant qu'utilisateur `www-data` (compat. avec ScoDoc7):
|
||||||
|
|
||||||
|
flask db init
|
||||||
|
flask db migrate -m "users and roles tables"
|
||||||
|
flask db upgrade
|
||||||
|
|
||||||
|
Puis initialisation de l'appli:
|
||||||
|
|
||||||
|
flask user-db-init
|
||||||
|
|
||||||
|
On peut ensuite créer des utilisateurs tests avec:
|
||||||
|
|
||||||
|
flask user-create toto Ens RT
|
||||||
|
flask user-create tata Ens RT
|
||||||
|
flask user-create tutu Ens Info
|
||||||
|
flask user-create titi Secr RT
|
||||||
|
|
||||||
|
|
||||||
### Bidouilles temporaires
|
### Bidouilles temporaires
|
||||||
|
|
||||||
Installer le bon vieux `pyExcelerator` dans l'environnement:
|
Installer le bon vieux `pyExcelerator` dans l'environnement:
|
||||||
|
@ -68,12 +68,15 @@ def create_app(config_class=Config):
|
|||||||
|
|
||||||
from app.views import scolar_bp
|
from app.views import scolar_bp
|
||||||
from app.views import notes_bp
|
from app.views import notes_bp
|
||||||
|
from app.views import users_bp
|
||||||
from app.views import absences_bp
|
from app.views import absences_bp
|
||||||
|
|
||||||
# https://scodoc.fr/ScoDoc/RT/Scolarite/...
|
# https://scodoc.fr/ScoDoc/RT/Scolarite/...
|
||||||
app.register_blueprint(scolar_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite")
|
app.register_blueprint(scolar_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite")
|
||||||
# https://scodoc.fr/ScoDoc/RT/Scolarite/Notes/...
|
# https://scodoc.fr/ScoDoc/RT/Scolarite/Notes/...
|
||||||
app.register_blueprint(notes_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Notes")
|
app.register_blueprint(notes_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Notes")
|
||||||
|
# https://scodoc.fr/ScoDoc/RT/Scolarite/Users/...
|
||||||
|
app.register_blueprint(users_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Users")
|
||||||
# https://scodoc.fr/ScoDoc/RT/Scolarite/Absences/...
|
# https://scodoc.fr/ScoDoc/RT/Scolarite/Absences/...
|
||||||
app.register_blueprint(
|
app.register_blueprint(
|
||||||
absences_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Absences"
|
absences_bp, url_prefix="/ScoDoc/<scodoc_dept>/Scolarite/Absences"
|
||||||
|
@ -16,14 +16,14 @@ _l = _
|
|||||||
|
|
||||||
|
|
||||||
class LoginForm(FlaskForm):
|
class LoginForm(FlaskForm):
|
||||||
username = StringField(_l("Username"), validators=[DataRequired()])
|
user_name = StringField(_l("Username"), validators=[DataRequired()])
|
||||||
password = PasswordField(_l("Password"), validators=[DataRequired()])
|
password = PasswordField(_l("Password"), validators=[DataRequired()])
|
||||||
remember_me = BooleanField(_l("Remember Me"))
|
remember_me = BooleanField(_l("Remember Me"))
|
||||||
submit = SubmitField(_l("Sign In"))
|
submit = SubmitField(_l("Sign In"))
|
||||||
|
|
||||||
|
|
||||||
class UserCreationForm(FlaskForm):
|
class UserCreationForm(FlaskForm):
|
||||||
username = StringField(_l("Username"), validators=[DataRequired()])
|
user_name = StringField(_l("Username"), validators=[DataRequired()])
|
||||||
email = StringField(_l("Email"), validators=[DataRequired(), Email()])
|
email = StringField(_l("Email"), validators=[DataRequired(), Email()])
|
||||||
password = PasswordField(_l("Password"), validators=[DataRequired()])
|
password = PasswordField(_l("Password"), validators=[DataRequired()])
|
||||||
password2 = PasswordField(
|
password2 = PasswordField(
|
||||||
@ -31,10 +31,10 @@ class UserCreationForm(FlaskForm):
|
|||||||
)
|
)
|
||||||
submit = SubmitField(_l("Register"))
|
submit = SubmitField(_l("Register"))
|
||||||
|
|
||||||
def validate_username(self, username):
|
def validate_user_name(self, user_name):
|
||||||
user = User.query.filter_by(username=username.data).first()
|
user = User.query.filter_by(user_name=user_name.data).first()
|
||||||
if user is not None:
|
if user is not None:
|
||||||
raise ValidationError(_("Please use a different username."))
|
raise ValidationError(_("Please use a different user_name."))
|
||||||
|
|
||||||
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()
|
||||||
|
@ -26,13 +26,23 @@ class User(UserMixin, db.Model):
|
|||||||
"""ScoDoc users, handled by Flask / SQLAlchemy"""
|
"""ScoDoc users, handled by Flask / SQLAlchemy"""
|
||||||
|
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
username = db.Column(db.String(64), index=True, unique=True)
|
user_name = db.Column(db.String(64), index=True, unique=True)
|
||||||
email = db.Column(db.String(120), index=True, unique=True)
|
email = db.Column(db.String(120), index=True, unique=True)
|
||||||
|
|
||||||
|
nom = db.Column(db.String(64))
|
||||||
|
prenom = db.Column(db.String(64))
|
||||||
|
dept = db.Column(db.String(32), index=True)
|
||||||
|
is_old = db.Column(db.Boolean, default=False, index=True)
|
||||||
|
|
||||||
password_hash = db.Column(db.String(128))
|
password_hash = db.Column(db.String(128))
|
||||||
about_me = db.Column(db.String(140))
|
|
||||||
last_seen = db.Column(db.DateTime, default=datetime.utcnow)
|
last_seen = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
date_modif_passwd = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
date_created = db.Column(db.DateTime, default=datetime.utcnow)
|
||||||
|
date_expiration = db.Column(db.DateTime, default=None)
|
||||||
|
passwd_temp = db.Column(db.Boolean, default=False)
|
||||||
token = db.Column(db.String(32), index=True, unique=True)
|
token = db.Column(db.String(32), index=True, unique=True)
|
||||||
token_expiration = db.Column(db.DateTime)
|
token_expiration = db.Column(db.DateTime)
|
||||||
|
|
||||||
roles = db.relationship("Role", secondary="user_role", viewonly=True)
|
roles = db.relationship("Role", secondary="user_role", viewonly=True)
|
||||||
Permission = Permission
|
Permission = Permission
|
||||||
|
|
||||||
@ -52,10 +62,10 @@ class User(UserMixin, db.Model):
|
|||||||
current_app.logger.info("creating user with roles={}".format(self.roles))
|
current_app.logger.info("creating user with roles={}".format(self.roles))
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<User {}>".format(self.username)
|
return "<User {u.user_name} id={u.id} dept={u.dept}>".format(u=self)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.username
|
return self.user_name
|
||||||
|
|
||||||
def set_password(self, password):
|
def set_password(self, password):
|
||||||
"Set password"
|
"Set password"
|
||||||
@ -91,17 +101,32 @@ class User(UserMixin, db.Model):
|
|||||||
|
|
||||||
def to_dict(self, include_email=False):
|
def to_dict(self, include_email=False):
|
||||||
data = {
|
data = {
|
||||||
|
"date_expiration": self.date_expiration.isoformat() + "Z"
|
||||||
|
if self.date_expiration
|
||||||
|
else None,
|
||||||
|
"date_modif_passwd": self.date_modif_passwd.isoformat() + "Z"
|
||||||
|
if self.date_modif_passwd
|
||||||
|
else None,
|
||||||
|
"date_created": self.date_created.isoformat() + "Z"
|
||||||
|
if self.date_created
|
||||||
|
else None,
|
||||||
|
"dept": self.dept,
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"username": self.username,
|
"is_old": self.is_old,
|
||||||
|
"status_txt": "(ancien)" if self.is_old else "",
|
||||||
"last_seen": self.last_seen.isoformat() + "Z",
|
"last_seen": self.last_seen.isoformat() + "Z",
|
||||||
"about_me": self.about_me,
|
"nom": self.nom,
|
||||||
|
"prenom": self.prenom,
|
||||||
|
"roles": self.roles,
|
||||||
|
"roles_string": self.get_roles_string(),
|
||||||
|
"user_name": self.user_name,
|
||||||
}
|
}
|
||||||
if include_email:
|
if include_email:
|
||||||
data["email"] = self.email
|
data["email"] = self.email
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def from_dict(self, data, new_user=False):
|
def from_dict(self, data, new_user=False):
|
||||||
for field in ["username", "email", "about_me"]:
|
for field in ["user_name", "non", "prenom", "dept", "status", "email"]:
|
||||||
if field in data:
|
if field in data:
|
||||||
setattr(self, field, data[field])
|
setattr(self, field, data[field])
|
||||||
if new_user and "password" in data:
|
if new_user and "password" in data:
|
||||||
@ -169,6 +194,12 @@ class User(UserMixin, db.Model):
|
|||||||
for role in self.roles:
|
for role in self.roles:
|
||||||
yield role
|
yield role
|
||||||
|
|
||||||
|
def get_roles_string(self):
|
||||||
|
"""string repr. of user's roles (with depts)
|
||||||
|
e.g. "EnsRT, EnsInfo, SecrCJ"
|
||||||
|
"""
|
||||||
|
return ", ".join("{r.role.name}{r.dept}".format(r=r) for r in self.user_roles)
|
||||||
|
|
||||||
def is_administrator(self):
|
def is_administrator(self):
|
||||||
return self.has_permission(Permission.ScoSuperAdmin, None)
|
return self.has_permission(Permission.ScoSuperAdmin, None)
|
||||||
|
|
||||||
|
@ -15,9 +15,11 @@ from app.auth.forms import (
|
|||||||
ResetPasswordRequestForm,
|
ResetPasswordRequestForm,
|
||||||
ResetPasswordForm,
|
ResetPasswordForm,
|
||||||
)
|
)
|
||||||
|
from app.auth.models import Permission
|
||||||
from app.auth.models import User
|
from app.auth.models import User
|
||||||
from app.auth.email import send_password_reset_email
|
from app.auth.email import send_password_reset_email
|
||||||
from app.decorators import scodoc7func, admin_required
|
from app.decorators import admin_required
|
||||||
|
|
||||||
|
|
||||||
_ = lambda x: x # sans babel
|
_ = lambda x: x # sans babel
|
||||||
_l = _
|
_l = _
|
||||||
@ -29,9 +31,9 @@ def login():
|
|||||||
return redirect(url_for("main.index"))
|
return redirect(url_for("main.index"))
|
||||||
form = LoginForm()
|
form = LoginForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
user = User.query.filter_by(username=form.username.data).first()
|
user = User.query.filter_by(user_name=form.user_name.data).first()
|
||||||
if user is None or not user.check_password(form.password.data):
|
if user is None or not user.check_password(form.password.data):
|
||||||
flash(_("Invalid username or password"))
|
flash(_("Invalid user_name or password"))
|
||||||
return redirect(url_for("auth.login"))
|
return redirect(url_for("auth.login"))
|
||||||
login_user(user, remember=form.remember_me.data)
|
login_user(user, remember=form.remember_me.data)
|
||||||
next_page = request.args.get("next")
|
next_page = request.args.get("next")
|
||||||
@ -53,11 +55,11 @@ def create_user():
|
|||||||
"Form creating new user"
|
"Form creating new user"
|
||||||
form = UserCreationForm()
|
form = UserCreationForm()
|
||||||
if form.validate_on_submit():
|
if form.validate_on_submit():
|
||||||
user = User(username=form.username.data, email=form.email.data)
|
user = User(user_name=form.user_name.data, email=form.email.data)
|
||||||
user.set_password(form.password.data)
|
user.set_password(form.password.data)
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
flash("User {} created".format(user.username))
|
flash("User {} created".format(user.user_name))
|
||||||
return redirect(url_for("main.index"))
|
return redirect(url_for("main.index"))
|
||||||
return render_template(
|
return render_template(
|
||||||
"auth/register.html", title=u"Création utilisateur", form=form
|
"auth/register.html", title=u"Création utilisateur", form=form
|
||||||
|
@ -26,7 +26,7 @@ class ZUser(object):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"create, based on `flask_login.current_user`"
|
"create, based on `flask_login.current_user`"
|
||||||
self.username = current_user.username
|
self.username = current_user.user_name
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return self.username
|
return self.username
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
|
|
||||||
"""Page accueil département (liste des semestres, etc)
|
"""Page accueil département (liste des semestres, etc)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from flask import g
|
||||||
|
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
@ -37,6 +40,7 @@ from app.scodoc import sco_modalites
|
|||||||
from app.scodoc import sco_news
|
from app.scodoc import sco_news
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_up_to_date
|
from app.scodoc import sco_up_to_date
|
||||||
|
from app.scodoc import sco_users
|
||||||
|
|
||||||
|
|
||||||
def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
||||||
@ -90,7 +94,7 @@ def index_html(context, REQUEST=None, showcodes=0, showsemtable=0):
|
|||||||
sem["groupicon"] = emptygroupicon
|
sem["groupicon"] = emptygroupicon
|
||||||
|
|
||||||
# S'il n'y a pas d'utilisateurs dans la base, affiche message
|
# S'il n'y a pas d'utilisateurs dans la base, affiche message
|
||||||
if not context.Users.get_userlist():
|
if not sco_users.get_user_list(dept=g.scodoc_dept):
|
||||||
H.append(
|
H.append(
|
||||||
"""<h2>Aucun utilisateur défini !</h2><p>Pour définir des utilisateurs
|
"""<h2>Aucun utilisateur défini !</h2><p>Pour définir des utilisateurs
|
||||||
<a href="Users">passez par la page Utilisateurs</a>.
|
<a href="Users">passez par la page Utilisateurs</a>.
|
||||||
|
@ -43,6 +43,7 @@ from app.scodoc import sco_compute_moy
|
|||||||
from app.scodoc import sco_edit_matiere
|
from app.scodoc import sco_edit_matiere
|
||||||
from app.scodoc import sco_edit_module
|
from app.scodoc import sco_edit_module
|
||||||
from app.scodoc import sco_edit_ue
|
from app.scodoc import sco_edit_ue
|
||||||
|
from app.scodoc import sco_etud
|
||||||
from app.scodoc import sco_evaluations
|
from app.scodoc import sco_evaluations
|
||||||
from app.scodoc import sco_formations
|
from app.scodoc import sco_formations
|
||||||
from app.scodoc import sco_formsemestre
|
from app.scodoc import sco_formsemestre
|
||||||
@ -52,7 +53,7 @@ from app.scodoc import sco_parcours_dut
|
|||||||
from app.scodoc import sco_permissions_check
|
from app.scodoc import sco_permissions_check
|
||||||
from app.scodoc import sco_portal_apogee
|
from app.scodoc import sco_portal_apogee
|
||||||
from app.scodoc import sco_preferences
|
from app.scodoc import sco_preferences
|
||||||
from app.scodoc import sco_etud
|
from app.scodoc import sco_users
|
||||||
|
|
||||||
|
|
||||||
def _default_sem_title(F):
|
def _default_sem_title(F):
|
||||||
@ -139,7 +140,7 @@ def do_formsemestre_createwithmodules(context, REQUEST=None, edit=False):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
||||||
userlist = context.Users.get_userlist()
|
userlist = [sco_users.user_info(u) for u in sco_users.get_user_list()]
|
||||||
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
||||||
for u in userlist:
|
for u in userlist:
|
||||||
login2display[u["user_name"]] = u["nomplogin"]
|
login2display[u["user_name"]] = u["nomplogin"]
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
"""Functions checking permissions for some common operations
|
"""Functions checking permissions for some common operations
|
||||||
"""
|
"""
|
||||||
|
from flask import g
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
import app.scodoc.notesdb as ndb
|
import app.scodoc.notesdb as ndb
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
@ -188,3 +190,26 @@ def can_change_groups(context, REQUEST, formsemestre_id):
|
|||||||
if uid in sem["responsables"]:
|
if uid in sem["responsables"]:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def can_handle_passwd(user, allow_admindepts=False):
|
||||||
|
"""True if the current user can see or change passwd info of user.
|
||||||
|
If allow_admindepts, allow Admin from all depts (so they can view users from other depts
|
||||||
|
and add roles to them).
|
||||||
|
user is a User instance.
|
||||||
|
"""
|
||||||
|
if current_user.is_administrator():
|
||||||
|
return True # super admin
|
||||||
|
# Anyone can change his own passwd (or see his informations)
|
||||||
|
if user.user_name == current_user.user_name:
|
||||||
|
return True
|
||||||
|
# If don't have permission in the current dept, abort
|
||||||
|
if not current_user.has_permission(Permission.ScoUsersAdmin, g.scodoc_dept):
|
||||||
|
return False
|
||||||
|
# Now check that current_user can manage users from this departement
|
||||||
|
if not current_user.dept:
|
||||||
|
return True # if no dept, can access users from all depts !
|
||||||
|
if (current_user.dept == user.dept) or allow_admindepts:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
@ -28,12 +28,48 @@
|
|||||||
"""Fonctions sur les utilisateurs
|
"""Fonctions sur les utilisateurs
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Anciennement dans ZScoUsers.py, séparé pour migration
|
# Anciennement ZScoUsers.py, fonctions de gestion des données réécrite avec flask/SQLAlchemy
|
||||||
|
|
||||||
|
import string
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import md5
|
||||||
|
import base64
|
||||||
|
import jaxml
|
||||||
|
|
||||||
|
from flask import current_app, url_for, g
|
||||||
|
from flask_login import current_user
|
||||||
|
|
||||||
import cracklib # pylint: disable=import-error
|
import cracklib # pylint: disable=import-error
|
||||||
|
|
||||||
|
|
||||||
|
from app.auth.models import Permission
|
||||||
|
from app.auth.models import User
|
||||||
|
|
||||||
|
from app.scodoc import html_sco_header
|
||||||
|
from app.scodoc import sco_cache
|
||||||
|
from app.scodoc import sco_etud
|
||||||
|
from app.scodoc import sco_excel
|
||||||
|
from app.scodoc import sco_import_users
|
||||||
|
from app.scodoc import sco_preferences
|
||||||
|
from app.scodoc.gen_tables import GenTable
|
||||||
|
from app.scodoc.notes_log import log
|
||||||
|
from app.scodoc.sco_permissions_check import can_handle_passwd
|
||||||
|
from app.scodoc.scolog import logdb
|
||||||
|
from app.scodoc.sco_etud import format_prenom, format_nom
|
||||||
|
from app.scodoc.TrivialFormulator import TrivialFormulator, tf_error_message
|
||||||
|
import app.scodoc.notesdb as ndb
|
||||||
import app.scodoc.sco_utils as scu
|
import app.scodoc.sco_utils as scu
|
||||||
|
|
||||||
|
from app.scodoc.sco_exceptions import (
|
||||||
|
AccessDenied,
|
||||||
|
ScoException,
|
||||||
|
ScoValueError,
|
||||||
|
ScoInvalidDateError,
|
||||||
|
ScoLockedFormError,
|
||||||
|
ScoGenError,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_valid_password(cleartxt):
|
def is_valid_password(cleartxt):
|
||||||
"""Check password.
|
"""Check password.
|
||||||
@ -50,3 +86,170 @@ def is_valid_password(cleartxt):
|
|||||||
return True
|
return True
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------
|
||||||
|
|
||||||
|
# ---------------
|
||||||
|
# XXX TODO supprimer ndb.GetUsersDBConnexion
|
||||||
|
|
||||||
|
|
||||||
|
def index_html(context, REQUEST, all_depts=False, with_olds=False, format="html"):
|
||||||
|
"gestion utilisateurs..."
|
||||||
|
all_depts = int(all_depts)
|
||||||
|
with_olds = int(with_olds)
|
||||||
|
|
||||||
|
H = [html_sco_header.html_sem_header(context, REQUEST, "Gestion des utilisateurs")]
|
||||||
|
H.append("<h2>Gestion des utilisateurs</h2>")
|
||||||
|
|
||||||
|
if current_user.has_permission(Permission.ScoUsersAdmin, g.scodoc_dept):
|
||||||
|
H.append(
|
||||||
|
'<p><a href="{}" class="stdlink">Ajouter un utilisateur</a>'.format(
|
||||||
|
url_for("users.create_user_form", scodoc_dept=g.scodoc_dept).encode(
|
||||||
|
scu.SCO_ENCODING
|
||||||
|
) # sco8
|
||||||
|
)
|
||||||
|
)
|
||||||
|
H.append(
|
||||||
|
' <a href="{}" class="stdlink">Importer des utilisateurs</a></p>'.format(
|
||||||
|
url_for("users.import_users_form", scodoc_dept=g.scodoc_dept).encode(
|
||||||
|
scu.SCO_ENCODING
|
||||||
|
) # sco8
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if all_depts:
|
||||||
|
checked = "checked"
|
||||||
|
else:
|
||||||
|
checked = ""
|
||||||
|
if with_olds:
|
||||||
|
olds_checked = "checked"
|
||||||
|
else:
|
||||||
|
olds_checked = ""
|
||||||
|
H.append(
|
||||||
|
"""<p><form name="f" action="%s" method="get">
|
||||||
|
<input type="checkbox" name="all_depts" value="1" onchange="document.f.submit();" %s>Tous les départements</input>
|
||||||
|
<input type="checkbox" name="with_olds" value="1" onchange="document.f.submit();" %s>Avec anciens utilisateurs</input>
|
||||||
|
</form></p>"""
|
||||||
|
% (REQUEST.URL0, checked, olds_checked)
|
||||||
|
)
|
||||||
|
|
||||||
|
L = list_users(
|
||||||
|
context,
|
||||||
|
g.scodoc_dept,
|
||||||
|
all_depts=all_depts,
|
||||||
|
with_olds=with_olds,
|
||||||
|
format=format,
|
||||||
|
REQUEST=REQUEST,
|
||||||
|
with_links=current_user.has_permission(Permission.ScoUsersAdmin, g.scodoc_dept),
|
||||||
|
)
|
||||||
|
if format != "html":
|
||||||
|
return L
|
||||||
|
H.append(L)
|
||||||
|
|
||||||
|
F = html_sco_header.sco_footer(context, REQUEST)
|
||||||
|
return "\n".join(H) + F
|
||||||
|
|
||||||
|
|
||||||
|
def list_users(
|
||||||
|
context,
|
||||||
|
dept,
|
||||||
|
all_depts=False, # tous les departements
|
||||||
|
with_olds=False, # inclut les anciens utilisateurs (status "old")
|
||||||
|
format="html",
|
||||||
|
with_links=True,
|
||||||
|
REQUEST=None,
|
||||||
|
):
|
||||||
|
"List users, returns a table in the specified format"
|
||||||
|
if dept and not all_depts:
|
||||||
|
users = get_user_list(dept=dept, with_olds=with_olds)
|
||||||
|
comm = "dept. %s" % dept.encode(scu.SCO_ENCODING) # sco8
|
||||||
|
else:
|
||||||
|
r = get_user_list(with_olds=with_olds)
|
||||||
|
comm = "tous"
|
||||||
|
if with_olds:
|
||||||
|
comm += ", avec anciens"
|
||||||
|
comm = "(" + comm + ")"
|
||||||
|
# -- Add some information and links:
|
||||||
|
r = []
|
||||||
|
for u in users:
|
||||||
|
# Can current user modify this user ?
|
||||||
|
can_modify = can_handle_passwd(u, allow_admindepts=True)
|
||||||
|
|
||||||
|
d = u.to_dict()
|
||||||
|
r.append(d)
|
||||||
|
# Add links
|
||||||
|
if with_links and can_modify:
|
||||||
|
target = url_for(
|
||||||
|
"users.userinfo", scodoc_dept=g.scodoc_dept, user_name=u.user_name
|
||||||
|
).encode(
|
||||||
|
scu.SCO_ENCODING
|
||||||
|
) # sco8
|
||||||
|
d["_user_name_target"] = target
|
||||||
|
d["_nom_target"] = target
|
||||||
|
d["_prenom_target"] = target
|
||||||
|
|
||||||
|
# Hide passwd modification date (depending on visitor's permission)
|
||||||
|
if not can_modify:
|
||||||
|
d["date_modif_passwd"] = "(non visible)"
|
||||||
|
|
||||||
|
title = "Utilisateurs définis dans ScoDoc"
|
||||||
|
tab = GenTable(
|
||||||
|
rows=r,
|
||||||
|
columns_ids=(
|
||||||
|
"user_name",
|
||||||
|
"nom_fmt",
|
||||||
|
"prenom_fmt",
|
||||||
|
"email",
|
||||||
|
"dept",
|
||||||
|
"roles_string",
|
||||||
|
"date_expiration",
|
||||||
|
"date_modif_passwd",
|
||||||
|
"passwd_temp",
|
||||||
|
"status_txt",
|
||||||
|
),
|
||||||
|
titles={
|
||||||
|
"user_name": "Login",
|
||||||
|
"nom_fmt": "Nom",
|
||||||
|
"prenom_fmt": "Prénom",
|
||||||
|
"email": "Mail",
|
||||||
|
"dept": "Dept.",
|
||||||
|
"roles": "Rôles",
|
||||||
|
"date_expiration": "Expiration",
|
||||||
|
"date_modif_passwd": "Modif. mot de passe",
|
||||||
|
"passwd_temp": "Temp.",
|
||||||
|
"status_txt": "Etat",
|
||||||
|
},
|
||||||
|
caption=title,
|
||||||
|
page_title="title",
|
||||||
|
html_title="""<h2>%d utilisateurs %s</h2>
|
||||||
|
<p class="help">Cliquer sur un nom pour changer son mot de passe</p>"""
|
||||||
|
% (len(r), comm),
|
||||||
|
html_class="table_leftalign list_users",
|
||||||
|
html_with_td_classes=True,
|
||||||
|
html_sortable=True,
|
||||||
|
base_url="%s?all=%s" % (REQUEST.URL0, all),
|
||||||
|
pdf_link=False, # table is too wide to fit in a paper page => disable pdf
|
||||||
|
preferences=sco_preferences.SemPreferences(context),
|
||||||
|
)
|
||||||
|
|
||||||
|
return tab.make_page(
|
||||||
|
context, format=format, with_html_headers=False, REQUEST=REQUEST
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_user_list(dept=None, with_olds=False):
|
||||||
|
"""Returns list of users.
|
||||||
|
If dept, select users from this dept,
|
||||||
|
else return all users.
|
||||||
|
"""
|
||||||
|
# was get_userlist
|
||||||
|
q = User.query
|
||||||
|
if dept is not None:
|
||||||
|
q = q.filter_by(dept=dept)
|
||||||
|
if not with_olds:
|
||||||
|
q = q.filter_by(is_old=False)
|
||||||
|
return q.all()
|
||||||
|
|
||||||
|
|
||||||
|
# def get_user_infos(user_list):
|
||||||
|
# return [ user_info(u) for u in user_list ]
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
{% if current_user.is_anonymous %}
|
{% if current_user.is_anonymous %}
|
||||||
<li><a href="{{ url_for('auth.login') }}">Login</a></li>
|
<li><a href="{{ url_for('auth.login') }}">Login</a></li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li>{{current_user.username}}</li>
|
<li>{{current_user.user_name}}</li>
|
||||||
<li><a href="{{ url_for('auth.logout') }}">Logout</a></li>
|
<li><a href="{{ url_for('auth.logout') }}">Logout</a></li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<p>Bonjour {{ user.username }},</p>
|
<p>Bonjour {{ user.user_name }},</p>
|
||||||
<p>
|
<p>
|
||||||
Pour réinitialiser votre mot de passe ScoDoc,
|
Pour réinitialiser votre mot de passe ScoDoc,
|
||||||
<a href="{{ url_for('auth.reset_password', token=token, _external=True) }}">
|
<a href="{{ url_for('auth.reset_password', token=token, _external=True) }}">
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Bonjour {{ user.username }},
|
Bonjour {{ user.user_name }},
|
||||||
|
|
||||||
Pour réinitialiser votre mot de passe ScoDoc, suivre le lien:
|
Pour réinitialiser votre mot de passe ScoDoc, suivre le lien:
|
||||||
|
|
||||||
|
@ -5,9 +5,10 @@ from flask import Blueprint
|
|||||||
|
|
||||||
scolar_bp = Blueprint("scolar", __name__)
|
scolar_bp = Blueprint("scolar", __name__)
|
||||||
notes_bp = Blueprint("notes", __name__)
|
notes_bp = Blueprint("notes", __name__)
|
||||||
|
users_bp = Blueprint("users", __name__)
|
||||||
absences_bp = Blueprint("absences", __name__)
|
absences_bp = Blueprint("absences", __name__)
|
||||||
essais_bp = Blueprint("essais", __name__)
|
essais_bp = Blueprint("essais", __name__)
|
||||||
|
|
||||||
from app.views import notes, scolar, absences, essais
|
from app.views import notes, scolar, absences, users, essais
|
||||||
|
|
||||||
scolar.context.Notes = notes.context # XXX transitoire #sco8
|
scolar.context.Notes = notes.context # XXX transitoire #sco8
|
||||||
|
@ -123,6 +123,7 @@ from app.scodoc import sco_synchro_etuds
|
|||||||
from app.scodoc import sco_tag_module
|
from app.scodoc import sco_tag_module
|
||||||
from app.scodoc import sco_ue_external
|
from app.scodoc import sco_ue_external
|
||||||
from app.scodoc import sco_undo_notes
|
from app.scodoc import sco_undo_notes
|
||||||
|
from app.scodoc import sco_users
|
||||||
from app.scodoc.gen_tables import GenTable
|
from app.scodoc.gen_tables import GenTable
|
||||||
from app.scodoc.sco_pdf import PDFLOCK
|
from app.scodoc.sco_pdf import PDFLOCK
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
@ -712,7 +713,7 @@ def edit_enseignants_form(context, REQUEST, moduleimpl_id):
|
|||||||
footer = html_sco_header.sco_footer(context, REQUEST)
|
footer = html_sco_header.sco_footer(context, REQUEST)
|
||||||
|
|
||||||
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
||||||
userlist = context.Users.get_userlist()
|
userlist = sco_users.get_user_list()
|
||||||
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
||||||
for u in userlist:
|
for u in userlist:
|
||||||
login2display[u["user_name"]] = u["nomplogin"]
|
login2display[u["user_name"]] = u["nomplogin"]
|
||||||
@ -821,9 +822,9 @@ def edit_moduleimpl_resp(context, REQUEST, moduleimpl_id):
|
|||||||
bodyOnLoad="init_tf_form('')",
|
bodyOnLoad="init_tf_form('')",
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
help = """<p class="help">Taper le début du nom de l'enseignant.</p>"""
|
help_str = """<p class="help">Taper le début du nom de l'enseignant.</p>"""
|
||||||
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
# Liste des enseignants avec forme pour affichage / saisie avec suggestion
|
||||||
userlist = context.Users.get_userlist()
|
userlist = [sco_users.user_info(u) for u in sco_users.get_user_list()]
|
||||||
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
login2display = {} # user_name : forme pour affichage = "NOM Prenom (login)"
|
||||||
for u in userlist:
|
for u in userlist:
|
||||||
login2display[u["user_name"]] = u["nomplogin"]
|
login2display[u["user_name"]] = u["nomplogin"]
|
||||||
@ -863,7 +864,10 @@ def edit_moduleimpl_resp(context, REQUEST, moduleimpl_id):
|
|||||||
)
|
)
|
||||||
if tf[0] == 0:
|
if tf[0] == 0:
|
||||||
return (
|
return (
|
||||||
"\n".join(H) + tf[1] + help + html_sco_header.sco_footer(context, REQUEST)
|
"\n".join(H)
|
||||||
|
+ tf[1]
|
||||||
|
+ help_str
|
||||||
|
+ html_sco_header.sco_footer(context, REQUEST)
|
||||||
)
|
)
|
||||||
elif tf[0] == -1:
|
elif tf[0] == -1:
|
||||||
return REQUEST.RESPONSE.redirect(
|
return REQUEST.RESPONSE.redirect(
|
||||||
|
85
app/views/users.py
Normal file
85
app/views/users.py
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# ScoDoc
|
||||||
|
#
|
||||||
|
# Copyright (c) 1999 - 2021 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
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
"""
|
||||||
|
Module users: interface gestion utilisateurs
|
||||||
|
ré-écriture pour Flask ScoDoc7 / ZScoUsers.py
|
||||||
|
|
||||||
|
Vues s'appuyant sur auth et sco_users
|
||||||
|
|
||||||
|
Emmanuel Viennet, 2021
|
||||||
|
"""
|
||||||
|
|
||||||
|
from flask import g
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
|
from app.auth.models import Permission
|
||||||
|
from app.auth.models import User
|
||||||
|
from app.decorators import (
|
||||||
|
scodoc7func,
|
||||||
|
ScoDoc7Context,
|
||||||
|
permission_required,
|
||||||
|
admin_required,
|
||||||
|
login_required,
|
||||||
|
)
|
||||||
|
|
||||||
|
from app.scodoc import sco_users
|
||||||
|
|
||||||
|
from app.views import users_bp as bp
|
||||||
|
|
||||||
|
|
||||||
|
context = ScoDoc7Context("users") # sco8
|
||||||
|
|
||||||
|
|
||||||
|
# ------- Fonctions vraiment spécifiques à ScoDoc:
|
||||||
|
@bp.route("/")
|
||||||
|
@bp.route("/index_html")
|
||||||
|
@permission_required(Permission.ScoUsersView)
|
||||||
|
@scodoc7func(context)
|
||||||
|
def index_html(context, REQUEST, all_depts=False, with_olds=False, format="html"):
|
||||||
|
return sco_users.index_html(
|
||||||
|
context,
|
||||||
|
REQUEST=REQUEST,
|
||||||
|
all_depts=all_depts,
|
||||||
|
with_olds=with_olds,
|
||||||
|
format=format,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/create_user_form")
|
||||||
|
def create_user_form():
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/import_users_form")
|
||||||
|
def import_users_form():
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/userinfo")
|
||||||
|
def userinfo():
|
||||||
|
raise NotImplementedError()
|
@ -8,7 +8,7 @@ Usage:
|
|||||||
check_zope_usage.py publishedmethods.csv string-constants.txt
|
check_zope_usage.py publishedmethods.csv string-constants.txt
|
||||||
|
|
||||||
publishedmethods.csv : fichier texte, module et un nom de méthode / ligne
|
publishedmethods.csv : fichier texte, module et un nom de méthode / ligne
|
||||||
ZScoUsers get_userlist
|
ZScoUsers get_user_list
|
||||||
comme extrait par zopelistmethods.py
|
comme extrait par zopelistmethods.py
|
||||||
|
|
||||||
string-constants.txt : les constantes chaines, extraites par extract_code_strings.py
|
string-constants.txt : les constantes chaines, extraites par extract_code_strings.py
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
alembic==1.5.5
|
alembic==1.5.5
|
||||||
|
astroid==1.6.6
|
||||||
attrdict==2.0.1
|
attrdict==2.0.1
|
||||||
Babel==2.9.0
|
Babel==2.9.0
|
||||||
|
backports.functools-lru-cache==1.6.4
|
||||||
blinker==1.4
|
blinker==1.4
|
||||||
certifi==2021.5.30
|
certifi==2021.5.30
|
||||||
chardet==4.0.0
|
chardet==4.0.0
|
||||||
click==7.1.2
|
click==7.1.2
|
||||||
|
configparser==4.0.2
|
||||||
|
cracklib==2.9.3
|
||||||
dnspython==1.16.0
|
dnspython==1.16.0
|
||||||
dominate==2.6.0
|
dominate==2.6.0
|
||||||
email-validator==1.1.2
|
email-validator==1.1.2
|
||||||
|
enum34==1.1.10
|
||||||
Flask==1.1.4
|
Flask==1.1.4
|
||||||
Flask-Babel==2.0.0
|
Flask-Babel==2.0.0
|
||||||
Flask-Bootstrap==3.3.7.1
|
Flask-Bootstrap==3.3.7.1
|
||||||
@ -17,18 +22,23 @@ Flask-Migrate==2.7.0
|
|||||||
Flask-Moment==0.11.0
|
Flask-Moment==0.11.0
|
||||||
Flask-SQLAlchemy==2.4.4
|
Flask-SQLAlchemy==2.4.4
|
||||||
Flask-WTF==0.14.3
|
Flask-WTF==0.14.3
|
||||||
|
futures==3.3.0
|
||||||
icalendar==4.0.7
|
icalendar==4.0.7
|
||||||
idna==2.10
|
idna==2.10
|
||||||
|
isort==4.3.21
|
||||||
itsdangerous==1.1.0
|
itsdangerous==1.1.0
|
||||||
jaxml==3.2
|
jaxml==3.2
|
||||||
Jinja2==2.11.2
|
Jinja2==2.11.2
|
||||||
|
lazy-object-proxy==1.6.0
|
||||||
Mako==1.1.4
|
Mako==1.1.4
|
||||||
MarkupSafe==1.1.1
|
MarkupSafe==1.1.1
|
||||||
|
mccabe==0.6.1
|
||||||
Pillow==6.2.2
|
Pillow==6.2.2
|
||||||
pkg-resources==0.0.0
|
pkg-resources==0.0.0
|
||||||
psycopg2==2.8.6
|
psycopg2==2.8.6
|
||||||
pyExcelerator==0.6.3a0
|
pyExcelerator==0.6.3a0
|
||||||
PyJWT==1.7.1
|
PyJWT==1.7.1
|
||||||
|
pylint==1.9.5
|
||||||
PyRSS2Gen==1.1
|
PyRSS2Gen==1.1
|
||||||
python-dateutil==2.8.1
|
python-dateutil==2.8.1
|
||||||
python-dotenv==0.15.0
|
python-dotenv==0.15.0
|
||||||
@ -36,6 +46,7 @@ python-editor==1.0.4
|
|||||||
pytz==2021.1
|
pytz==2021.1
|
||||||
reportlab==3.5.59
|
reportlab==3.5.59
|
||||||
requests==2.25.1
|
requests==2.25.1
|
||||||
|
singledispatch==3.6.2
|
||||||
six==1.15.0
|
six==1.15.0
|
||||||
SQLAlchemy==1.3.23
|
SQLAlchemy==1.3.23
|
||||||
stripogram==1.5
|
stripogram==1.5
|
||||||
@ -43,4 +54,5 @@ typing==3.7.4.3
|
|||||||
urllib3==1.26.5
|
urllib3==1.26.5
|
||||||
visitor==0.1.3
|
visitor==0.1.3
|
||||||
Werkzeug==1.0.1
|
Werkzeug==1.0.1
|
||||||
|
wrapt==1.12.1
|
||||||
WTForms==2.3.3
|
WTForms==2.3.3
|
||||||
|
16
scodoc.py
16
scodoc.py
@ -52,14 +52,14 @@ def user_db_init():
|
|||||||
click.echo("created initial roles")
|
click.echo("created initial roles")
|
||||||
# Ensure that admin exists
|
# Ensure that admin exists
|
||||||
if Config.SCODOC_ADMIN_MAIL:
|
if Config.SCODOC_ADMIN_MAIL:
|
||||||
admin_username = Config.SCODOC_ADMIN_LOGIN
|
admin_user_name = Config.SCODOC_ADMIN_LOGIN
|
||||||
user = User.query.filter_by(username=admin_username).first()
|
user = User.query.filter_by(user_name=admin_user_name).first()
|
||||||
if not user:
|
if not user:
|
||||||
user = User(username=admin_username, email=Config.SCODOC_ADMIN_MAIL)
|
user = User(user_name=admin_user_name, email=Config.SCODOC_ADMIN_MAIL)
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
click.echo(
|
click.echo(
|
||||||
"created initial admin user, login: {u.username}, email: {u.email}".format(
|
"created initial admin user, login: {u.user_name}, email: {u.email}".format(
|
||||||
u=user
|
u=user
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -90,16 +90,16 @@ def user_create(username, role, dept):
|
|||||||
if not r:
|
if not r:
|
||||||
sys.stderr.write("user_create: role {r} does not exists".format(r=r))
|
sys.stderr.write("user_create: role {r} does not exists".format(r=r))
|
||||||
return 1
|
return 1
|
||||||
u = User.query.filter_by(username=username).first()
|
u = User.query.filter_by(user_name=username).first()
|
||||||
if u:
|
if u:
|
||||||
sys.stderr.write("user_create: user {u} already exists".format(u=u))
|
sys.stderr.write("user_create: user {u} already exists".format(u=u))
|
||||||
return 2
|
return 2
|
||||||
u = User(username=username)
|
u = User(user_name=username, dept=dept)
|
||||||
u.add_role(r, dept)
|
u.add_role(r, dept)
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
click.echo(
|
click.echo(
|
||||||
"created user, login: {u.username}, with role {r} in dept. {dept}".format(
|
"created user, login: {u.user_name}, with role {r} in dept. {dept}".format(
|
||||||
u=u, r=r, dept=dept
|
u=u, r=r, dept=dept
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -113,7 +113,7 @@ def user_password(username, password=None):
|
|||||||
if not password:
|
if not password:
|
||||||
sys.stderr.write("user_password: missing password")
|
sys.stderr.write("user_password: missing password")
|
||||||
return 1
|
return 1
|
||||||
u = User.query.filter_by(username=username).first()
|
u = User.query.filter_by(user_name=username).first()
|
||||||
if not u:
|
if not u:
|
||||||
sys.stderr.write("user_password: user {} does not exists".format(username))
|
sys.stderr.write("user_password: user {} does not exists".format(username))
|
||||||
return 1
|
return 1
|
||||||
|
@ -98,5 +98,5 @@ class FakeUsers(object):
|
|||||||
"date_expiration": None,
|
"date_expiration": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_userlist(self, dept=None, with_olds=False):
|
def get_user_list(self, dept=None, with_olds=False):
|
||||||
return [self.user_info()]
|
return [self.user_info()]
|
||||||
|
@ -30,7 +30,7 @@ class UserModelCase(unittest.TestCase):
|
|||||||
db.drop_all()
|
db.drop_all()
|
||||||
|
|
||||||
def test_password_hashing(self):
|
def test_password_hashing(self):
|
||||||
u = User(username="susan")
|
u = User(user_name="susan")
|
||||||
u.set_password("cat")
|
u.set_password("cat")
|
||||||
self.assertFalse(u.check_password("dog"))
|
self.assertFalse(u.check_password("dog"))
|
||||||
self.assertTrue(u.check_password("cat"))
|
self.assertTrue(u.check_password("cat"))
|
||||||
@ -68,7 +68,7 @@ class UserModelCase(unittest.TestCase):
|
|||||||
dept = "XX"
|
dept = "XX"
|
||||||
perm = Permission.ScoAbsChange
|
perm = Permission.ScoAbsChange
|
||||||
perm2 = Permission.ScoView
|
perm2 = Permission.ScoView
|
||||||
u = User(username="un enseignant")
|
u = User(user_name="un enseignant")
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
self.assertFalse(u.has_permission(perm, dept))
|
self.assertFalse(u.has_permission(perm, dept))
|
||||||
r = Role.get_named_role("Ens")
|
r = Role.get_named_role("Ens")
|
||||||
@ -76,7 +76,7 @@ class UserModelCase(unittest.TestCase):
|
|||||||
r = Role(name="Ens", permissions=perm)
|
r = Role(name="Ens", permissions=perm)
|
||||||
u.add_role(r, dept)
|
u.add_role(r, dept)
|
||||||
self.assertTrue(u.has_permission(perm, dept))
|
self.assertTrue(u.has_permission(perm, dept))
|
||||||
u = User(username="un autre")
|
u = User(user_name="un autre")
|
||||||
u.add_role(r, dept)
|
u.add_role(r, dept)
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@ -86,7 +86,7 @@ class UserModelCase(unittest.TestCase):
|
|||||||
r2 = Role(name="Secr", dept=dept, permissions=perm2)
|
r2 = Role(name="Secr", dept=dept, permissions=perm2)
|
||||||
u.add_roles([r, r2], dept)
|
u.add_roles([r, r2], dept)
|
||||||
self.assertTrue(len(u.roles) == 2)
|
self.assertTrue(len(u.roles) == 2)
|
||||||
u = User(username="encore un")
|
u = User(user_name="encore un")
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
u.set_roles([r, r2], dept)
|
u.set_roles([r, r2], dept)
|
||||||
@ -101,7 +101,7 @@ class UserModelCase(unittest.TestCase):
|
|||||||
def test_user_admin(self):
|
def test_user_admin(self):
|
||||||
dept = "XX"
|
dept = "XX"
|
||||||
perm = 0x1234 # a random perm
|
perm = 0x1234 # a random perm
|
||||||
u = User(username="un admin", email=current_app.config["SCODOC_ADMIN_MAIL"])
|
u = User(user_name="un admin", email=current_app.config["SCODOC_ADMIN_MAIL"])
|
||||||
db.session.add(u)
|
db.session.add(u)
|
||||||
self.assertTrue(len(u.roles) == 1)
|
self.assertTrue(len(u.roles) == 1)
|
||||||
self.assertTrue(u.has_permission(perm, dept))
|
self.assertTrue(u.has_permission(perm, dept))
|
||||||
|
Loading…
Reference in New Issue
Block a user