forked from ScoDoc/ScoDoc
Edition/créeation utilisateurs: choix département selon les permissions
This commit is contained in:
parent
2d2b2b2f39
commit
9cd31e66f0
@ -19,7 +19,8 @@ from werkzeug.security import generate_password_hash, check_password_hash
|
|||||||
import jwt
|
import jwt
|
||||||
|
|
||||||
from app import db, login
|
from app import db, login
|
||||||
|
from app.models import Departement
|
||||||
|
from app.models import SHORT_STR_LEN
|
||||||
from app.scodoc.sco_exceptions import ScoValueError
|
from app.scodoc.sco_exceptions import ScoValueError
|
||||||
from app.scodoc.sco_permissions import Permission
|
from app.scodoc.sco_permissions import Permission
|
||||||
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
|
from app.scodoc.sco_roles_default import SCO_ROLES_DEFAULTS
|
||||||
@ -55,7 +56,7 @@ class User(UserMixin, db.Model):
|
|||||||
|
|
||||||
nom = db.Column(db.String(64))
|
nom = db.Column(db.String(64))
|
||||||
prenom = db.Column(db.String(64))
|
prenom = db.Column(db.String(64))
|
||||||
dept = db.Column(db.String(32), index=True)
|
dept = db.Column(db.String(SHORT_STR_LEN), index=True)
|
||||||
active = db.Column(db.Boolean, default=True, index=True)
|
active = db.Column(db.Boolean, default=True, index=True)
|
||||||
|
|
||||||
password_hash = db.Column(db.String(128))
|
password_hash = db.Column(db.String(128))
|
||||||
@ -71,6 +72,13 @@ class User(UserMixin, db.Model):
|
|||||||
roles = db.relationship("Role", secondary="user_role", viewonly=True)
|
roles = db.relationship("Role", secondary="user_role", viewonly=True)
|
||||||
Permission = Permission
|
Permission = Permission
|
||||||
|
|
||||||
|
_departement = db.relationship(
|
||||||
|
"Departement",
|
||||||
|
foreign_keys=[Departement.acronym],
|
||||||
|
primaryjoin=(dept == Departement.acronym),
|
||||||
|
lazy="dynamic",
|
||||||
|
)
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.roles = []
|
self.roles = []
|
||||||
self.user_roles = []
|
self.user_roles = []
|
||||||
@ -221,6 +229,12 @@ class User(UserMixin, db.Model):
|
|||||||
return None
|
return None
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
def get_dept_id(self) -> int:
|
||||||
|
"returns user's department id, or None"
|
||||||
|
if self.dept:
|
||||||
|
return self._departement.first().id
|
||||||
|
return None
|
||||||
|
|
||||||
# Permissions management:
|
# Permissions management:
|
||||||
def has_permission(self, perm: int, dept=False):
|
def has_permission(self, perm: int, dept=False):
|
||||||
"""Check if user has permission `perm` in given `dept`.
|
"""Check if user has permission `perm` in given `dept`.
|
||||||
|
@ -167,10 +167,10 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
if edit:
|
if edit:
|
||||||
if not user_name:
|
if not user_name:
|
||||||
raise ValueError("missing argument: user_name")
|
raise ValueError("missing argument: user_name")
|
||||||
u = User.query.filter_by(user_name=user_name).first()
|
the_user = User.query.filter_by(user_name=user_name).first()
|
||||||
if not u:
|
if not the_user:
|
||||||
raise ScoValueError("utilisateur inexistant")
|
raise ScoValueError("utilisateur inexistant")
|
||||||
initvalues = u.to_dict()
|
initvalues = the_user.to_dict()
|
||||||
H.append("<h2>Modification de l'utilisateur %s</h2>" % user_name)
|
H.append("<h2>Modification de l'utilisateur %s</h2>" % user_name)
|
||||||
else:
|
else:
|
||||||
H.append("<h2>Création d'un utilisateur</h2>")
|
H.append("<h2>Création d'un utilisateur</h2>")
|
||||||
@ -197,11 +197,11 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
# sinon, les départements dans lesquels l'utilisateur a le droit
|
# sinon, les départements dans lesquels l'utilisateur a le droit
|
||||||
if is_super_admin:
|
if is_super_admin:
|
||||||
log("create_user_form called by %s (super admin)" % (current_user.user_name,))
|
log("create_user_form called by %s (super admin)" % (current_user.user_name,))
|
||||||
dept_ids = [d.acronym for d in Departement.query.all()]
|
administrable_dept_acronyms = [d.acronym for d in Departement.query.all()]
|
||||||
else:
|
else:
|
||||||
# Si on n'est pas SuperAdmin, liste les départements dans lesquels on a la
|
# Si on n'est pas SuperAdmin, liste les départements dans lesquels on a la
|
||||||
# permission ScoUsersAdmin
|
# permission ScoUsersAdmin
|
||||||
dept_ids = sorted(
|
administrable_dept_acronyms = sorted(
|
||||||
set(
|
set(
|
||||||
[
|
[
|
||||||
x.dept
|
x.dept
|
||||||
@ -211,7 +211,9 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
editable_roles_set = {(r, dept) for r in standard_roles for dept in dept_ids}
|
editable_roles_set = {
|
||||||
|
(r, dept) for r in standard_roles for dept in administrable_dept_acronyms
|
||||||
|
}
|
||||||
#
|
#
|
||||||
if not edit:
|
if not edit:
|
||||||
submitlabel = "Créer utilisateur"
|
submitlabel = "Créer utilisateur"
|
||||||
@ -224,9 +226,11 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
initvalues["roles"] = []
|
initvalues["roles"] = []
|
||||||
if "date_expiration" in initvalues:
|
if "date_expiration" in initvalues:
|
||||||
initvalues["date_expiration"] = (
|
initvalues["date_expiration"] = (
|
||||||
u.date_expiration.strftime("%d/%m/%Y") if u.date_expiration else ""
|
the_user.date_expiration.strftime("%d/%m/%Y")
|
||||||
|
if the_user.date_expiration
|
||||||
|
else ""
|
||||||
)
|
)
|
||||||
initvalues["status"] = "" if u.active else "old"
|
initvalues["status"] = "" if the_user.active else "old"
|
||||||
orig_roles = { # set des roles existants avant édition
|
orig_roles = { # set des roles existants avant édition
|
||||||
UserRole.role_dept_from_string(role_dept)
|
UserRole.role_dept_from_string(role_dept)
|
||||||
for role_dept in initvalues["roles"]
|
for role_dept in initvalues["roles"]
|
||||||
@ -347,11 +351,12 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
# Si auth n'a pas de departement (admin global)
|
||||||
|
# propose de choisir librement le dept du nouvel utilisateur
|
||||||
|
# sinon, menu proposant l'ensembe des départements dans lesquels
|
||||||
|
# nous avons la permission ScoUserAdmin + le dept actuel de l'utilisateur
|
||||||
|
# modifié.
|
||||||
if not auth_dept:
|
if not auth_dept:
|
||||||
# si auth n'a pas de departement (admin global)
|
|
||||||
# propose de choisir le dept du nouvel utilisateur
|
|
||||||
# sinon, il sera créé dans le même département que auth
|
|
||||||
descr.append(
|
descr.append(
|
||||||
(
|
(
|
||||||
"dept",
|
"dept",
|
||||||
@ -360,35 +365,57 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
"input_type": "text",
|
"input_type": "text",
|
||||||
"size": 12,
|
"size": 12,
|
||||||
"allow_null": True,
|
"allow_null": True,
|
||||||
"explanation": """département d\'appartenance de l\'utilisateur (s'il s'agit d'un administrateur, laisser vide si vous voulez qu'il puisse créer des utilisateurs dans d'autres départements)""",
|
"explanation": """département de rattachement de l'utilisateur
|
||||||
|
(s'il s'agit d'un administrateur, laisser vide si vous voulez
|
||||||
|
qu'il puisse créer des utilisateurs dans d'autres départements)
|
||||||
|
""",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
can_choose_dept = True
|
can_choose_dept = True
|
||||||
else:
|
else:
|
||||||
can_choose_dept = False
|
selectable_dept_acronyms = set(administrable_dept_acronyms)
|
||||||
if edit:
|
if edit: # ajoute dept actuel de l'utilisateur
|
||||||
|
selectable_dept_acronyms |= {the_user.dept}
|
||||||
|
if len(selectable_dept_acronyms) > 1:
|
||||||
|
can_choose_dept = True
|
||||||
|
selectable_dept_acronyms = sorted(list(selectable_dept_acronyms))
|
||||||
descr.append(
|
descr.append(
|
||||||
(
|
(
|
||||||
"d",
|
"dept",
|
||||||
{
|
{
|
||||||
"input_type": "separator",
|
"title": "Département",
|
||||||
"title": "L'utilisateur appartient au département %s"
|
"input_type": "menu",
|
||||||
% auth_dept,
|
"explanation": """département de rattachement de l'utilisateur""",
|
||||||
|
"labels": selectable_dept_acronyms,
|
||||||
|
"allowed_values": selectable_dept_acronyms,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else: # pas de choix de département
|
||||||
descr.append(
|
can_choose_dept = False
|
||||||
(
|
if edit:
|
||||||
"d",
|
descr.append(
|
||||||
{
|
(
|
||||||
"input_type": "separator",
|
"d",
|
||||||
"title": "L'utilisateur sera crée dans le département %s"
|
{
|
||||||
% auth_dept,
|
"input_type": "separator",
|
||||||
},
|
"title": "L'utilisateur appartient au département %s"
|
||||||
|
% auth_dept,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
descr.append(
|
||||||
|
(
|
||||||
|
"d",
|
||||||
|
{
|
||||||
|
"input_type": "separator",
|
||||||
|
"title": "L'utilisateur sera crée dans le département %s"
|
||||||
|
% auth_dept,
|
||||||
|
},
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
descr += [
|
descr += [
|
||||||
(
|
(
|
||||||
@ -512,6 +539,10 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
del vals["status"] # no one can't change its own status
|
del vals["status"] # no one can't change its own status
|
||||||
if "status" in vals:
|
if "status" in vals:
|
||||||
vals["active"] = vals["status"] == ""
|
vals["active"] = vals["status"] == ""
|
||||||
|
# Département:
|
||||||
|
if auth_dept: # pas super-admin
|
||||||
|
if vals["dept"] not in selectable_dept_acronyms:
|
||||||
|
del vals["dept"] # ne change pas de dept
|
||||||
# traitement des roles: ne doit pas affecter les roles
|
# traitement des roles: ne doit pas affecter les roles
|
||||||
# que l'on en controle pas:
|
# que l'on en controle pas:
|
||||||
for role in orig_roles_strings: # { "Ens_RT", "Secr_CJ", ... }
|
for role in orig_roles_strings: # { "Ens_RT", "Secr_CJ", ... }
|
||||||
@ -565,30 +596,37 @@ def create_user_form(user_name=None, edit=0, all_roles=1):
|
|||||||
"""Mot de passe trop simple, recommencez !"""
|
"""Mot de passe trop simple, recommencez !"""
|
||||||
)
|
)
|
||||||
return "\n".join(H) + msg + "\n" + tf[1] + F
|
return "\n".join(H) + msg + "\n" + tf[1] + F
|
||||||
|
# Département:
|
||||||
if not can_choose_dept:
|
if not can_choose_dept:
|
||||||
vals["dept"] = auth_dept
|
vals["dept"] = auth_dept
|
||||||
|
else:
|
||||||
|
if auth_dept: # pas super-admin
|
||||||
|
if vals["dept"] not in selectable_dept_acronyms:
|
||||||
|
raise ScoValueError("département invalide")
|
||||||
# ok, go
|
# ok, go
|
||||||
log(
|
log(
|
||||||
"sco_users: new_user %s by %s"
|
"sco_users: new_user %s by %s"
|
||||||
% (vals["user_name"], current_user.user_name)
|
% (vals["user_name"], current_user.user_name)
|
||||||
)
|
)
|
||||||
u = User()
|
the_user = User()
|
||||||
u.from_dict(vals, new_user=True)
|
the_user.from_dict(vals, new_user=True)
|
||||||
db.session.add(u)
|
db.session.add(the_user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
# envoi éventuel d'un message
|
# envoi éventuel d'un message
|
||||||
if mode == Mode.WELCOME_AND_CHANGE_PASSWORD or mode == Mode.WELCOME_ONLY:
|
if mode == Mode.WELCOME_AND_CHANGE_PASSWORD or mode == Mode.WELCOME_ONLY:
|
||||||
if mode == Mode.WELCOME_AND_CHANGE_PASSWORD:
|
if mode == Mode.WELCOME_AND_CHANGE_PASSWORD:
|
||||||
token = u.get_reset_password_token()
|
token = the_user.get_reset_password_token()
|
||||||
else:
|
else:
|
||||||
token = None
|
token = None
|
||||||
send_email(
|
send_email(
|
||||||
"[ScoDoc] Création de votre compte",
|
"[ScoDoc] Création de votre compte",
|
||||||
sender=from_mail, # current_app.config["ADMINS"][0],
|
sender=from_mail, # current_app.config["ADMINS"][0],
|
||||||
recipients=[u.email],
|
recipients=[the_user.email],
|
||||||
text_body=render_template("email/welcome.txt", user=u, token=token),
|
text_body=render_template(
|
||||||
|
"email/welcome.txt", user=the_user, token=token
|
||||||
|
),
|
||||||
html_body=render_template(
|
html_body=render_template(
|
||||||
"email/welcome.html", user=u, token=token
|
"email/welcome.html", user=the_user, token=token
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user