diff --git a/app/scodoc/TrivialFormulator.py b/app/scodoc/TrivialFormulator.py index ae7007683b..5b7020a8fe 100644 --- a/app/scodoc/TrivialFormulator.py +++ b/app/scodoc/TrivialFormulator.py @@ -730,11 +730,7 @@ var {field}_as = new bsn.AutoSuggest('{field}', {field}_opts); R.append("%s" % title) R.append('
Permissions de cet utilisateur dans le département {{dept}}:
+Permissions de cet utilisateur dans le département {{dept}}:
Vous êtes super administrateur !
""") - is_super_admin = True - - if all_roles: - # tous sauf SuperAdmin - standard_roles = [ - r - for r in Role.query.all() - if r.permissions != Permission.ALL_PERMISSIONS[0] - ] - else: - # Les rôles standards créés à l'initialisation de ScoDoc: - standard_roles = [ - Role.get_named_role(r) for r in sco_roles_default.ROLES_ATTRIBUABLES_DEPT - ] - # Départements auxquels ont peut associer des rôles via ce dialogue: - # si SuperAdmin, tous les rôles standards dans tous les départements - # sinon, les départements dans lesquels l'utilisateur a la permission ScoUsersAdmin - if is_super_admin: - log(f"create_user_form called by {current_user.user_name} (super admin)") - administrable_dept_acronyms = [d.acronym for d in Departement.query.all()] - else: - # Si on n'est pas SuperAdmin, liste les départements dans lesquels on a la - # permission ScoUsersAdmin - administrable_dept_acronyms = sorted( - set( - [ - x.dept or "" - for x in UserRole.query.filter_by(user=current_user) - if x.role.has_permission(Permission.ScoUsersAdmin) and x.dept - ] - ) - ) - - editable_roles_set = { - (r, dept) for r in standard_roles for dept in administrable_dept_acronyms - } - if current_user.is_administrator(): - editable_roles_set |= { - (Role.get_named_role(r), None) - for r in sco_roles_default.ROLES_ATTRIBUABLES_SCODOC - } - # Un super-admin peut nommer d'autres super-admin: - editable_roles_set |= {(Role.get_named_role("SuperAdmin"), None)} - # - if not edit: - submitlabel = "Créer utilisateur" - orig_roles = set() - else: submitlabel = "Modifier utilisateur" if "roles_string" in initvalues: initvalues["roles"] = initvalues["roles_string"].split(",") @@ -243,6 +250,26 @@ def create_user_form(user_name=None, edit=0, all_roles=False): } if not initvalues["active"]: editable_roles_set = set() # can't change roles of a disabled user + else: + H.append("Vous êtes super administrateur !
""") + + administrable_dept_acronyms = _get_administrable_depts() + if edit: + if the_user.dept is None: # seul le super admin peut le toucher + edit_only_roles = not current_user.is_administrator() + else: + edit_only_roles = the_user.dept not in administrable_dept_acronyms + else: + edit_only_roles = False # création nouvel utilisateur + editable_roles_set = _get_editable_roles( + administrable_dept_acronyms, all_roles=all_roles + ) editable_roles_strings = { r.name + "_" + (dept or "") for (r, dept) in editable_roles_set } @@ -265,12 +292,29 @@ def create_user_form(user_name=None, edit=0, all_roles=False): for i, role_string in enumerate(displayed_roles_strings): if role_string not in editable_roles_strings: disabled_roles[i] = True + # Formulaire: descr = [ ("edit", {"input_type": "hidden", "default": edit}), - ("nom", {"title": "Nom", "size": 20, "allow_null": False}), - ("prenom", {"title": "Prénom", "size": 20, "allow_null": False}), + ( + "nom", + { + "title": "Nom", + "size": 20, + "allow_null": False, + "readonly": edit_only_roles, + }, + ), + ( + "prenom", + { + "title": "Prénom", + "size": 20, + "allow_null": False, + "readonly": edit_only_roles, + }, + ), ] - if current_user.user_name != user_name: + if current_user.user_name != user_name and not edit_only_roles: # no one can change its own status descr.append( ( @@ -316,13 +360,12 @@ def create_user_form(user_name=None, edit=0, all_roles=False): }, ), ] - else: + else: # edition: on ne peut pas changer user_name descr += [ ( "user_name", {"input_type": "hidden", "default": initvalues["user_name"]}, - ), - ("user_name", {"input_type": "hidden", "default": initvalues["user_name"]}), + ) ] descr += [ ( @@ -330,9 +373,12 @@ def create_user_form(user_name=None, edit=0, all_roles=False): { "title": "e-mail", "input_type": "text", - "explanation": "requis, doit fonctionner", + "explanation": "requis, doit fonctionner" + if not edit_only_roles + else "", "size": 20, "allow_null": False, + "readonly": edit_only_roles, }, ) ] @@ -362,72 +408,50 @@ def create_user_form(user_name=None, edit=0, all_roles=False): }, ), ] - # 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: + # Si SuperAdmin, propose de choisir librement le dept du nouvel utilisateur + selectable_dept_acronyms = set(administrable_dept_acronyms) + if edit and the_user.dept is not None: # ajoute dept actuel de l'utilisateur + selectable_dept_acronyms |= {the_user.dept} + if is_super_admin and len(selectable_dept_acronyms) > 1: + selectable_dept_acronyms = sorted(list(selectable_dept_acronyms)) descr.append( ( "dept", { "title": "Département", - "input_type": "text", - "size": 12, - "allow_null": True, - "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) - """, + "input_type": "menu", + "explanation": """département de rattachement de l'utilisateur""", + "labels": selectable_dept_acronyms, + "allowed_values": selectable_dept_acronyms, + "default": g.scodoc_dept + if g.scodoc_dept in selectable_dept_acronyms + else (auth_dept or ""), }, ) ) can_choose_dept = True - else: - selectable_dept_acronyms = set(administrable_dept_acronyms) - if edit and the_user.dept is not None: # 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)) + else: # pas de choix de département + can_choose_dept = False + if edit: descr.append( ( - "dept", + "d", { - "title": "Département", - "input_type": "menu", - "explanation": """département de rattachement de l'utilisateur""", - "labels": selectable_dept_acronyms, - "allowed_values": selectable_dept_acronyms, - "default": g.scodoc_dept - if g.scodoc_dept in selectable_dept_acronyms - else "", + "input_type": "separator", + "title": f"""L'utilisateur appartient au département {the_user.dept or "(tous)"}""", }, ) ) - else: # pas de choix de département - can_choose_dept = False - if edit: - descr.append( - ( - "d", - { - "input_type": "separator", - "title": f"L'utilisateur appartient au département {auth_dept}", - }, - ) - ) - else: - descr.append( - ( - "d", - { - "input_type": "separator", - "title": f"L'utilisateur sera crée dans le département {auth_dept}", - }, - ) + else: + descr.append( + ( + "d", + { + "input_type": "separator", + "title": f"L'utilisateur sera crée dans le département {auth_dept}", + }, ) + ) descr += [ ( @@ -435,9 +459,12 @@ def create_user_form(user_name=None, edit=0, all_roles=False): { "title": "Date d'expiration", # j/m/a "input_type": "datedmy", - "explanation": "j/m/a, laisser vide si pas de limite", + "explanation": "j/m/a, laisser vide si pas de limite" + if not edit_only_roles + else "", "size": 9, "allow_null": True, + "readonly": edit_only_roles, }, ), ( @@ -451,17 +478,20 @@ def create_user_form(user_name=None, edit=0, all_roles=False): "disabled_items": disabled_roles, }, ), - ( - "force", - { - "title": "Ignorer les avertissements", - "input_type": "checkbox", - "explanation": "passer outre les avertissements (homonymes, etc)", - "labels": ("",), - "allowed_values": ("1",), - }, - ), ] + if not edit_only_roles: + descr += [ + ( + "force", + { + "title": "Ignorer les avertissements", + "input_type": "checkbox", + "explanation": "passer outre les avertissements (homonymes, etc)", + "labels": ("",), + "allowed_values": ("1",), + }, + ), + ] vals = scu.get_request_args() if "tf_submitted" in vals and "roles" not in vals: vals["roles"] = [] @@ -491,7 +521,7 @@ def create_user_form(user_name=None, edit=0, all_roles=False): else: edit = 0 try: - force = int(vals["force"][0]) + force = int(vals.get("force", "0")[0]) except (IndexError, ValueError, TypeError): force = 0 @@ -511,35 +541,37 @@ def create_user_form(user_name=None, edit=0, all_roles=False): if err: H.append(tf_error_message(f"""Erreur: {err}""")) return "\n".join(H) + "\n" + tf[1] + F - ok, msg = sco_users.check_modif_user( - edit, - enforce_optionals=not force, - user_name=user_name, - nom=vals["nom"], - prenom=vals["prenom"], - email=vals["email"], - dept=vals.get("dept", auth_dept), - roles=vals["roles"], - ) - if not ok: - H.append(tf_error_message(msg)) - return "\n".join(H) + "\n" + tf[1] + F - if "date_expiration" in vals: - try: - if vals["date_expiration"]: - vals["date_expiration"] = datetime.datetime.strptime( - vals["date_expiration"], "%d/%m/%Y" - ) - if vals["date_expiration"] < datetime.datetime.now(): - H.append(tf_error_message("date expiration passée")) - return "\n".join(H) + "\n" + tf[1] + F - else: - vals["date_expiration"] = None - except ValueError: - H.append(tf_error_message("date expiration invalide")) + if not edit_only_roles: + ok_modif, msg = sco_users.check_modif_user( + edit, + enforce_optionals=not force, + user_name=user_name, + nom=vals["nom"], + prenom=vals["prenom"], + email=vals["email"], + dept=vals.get("dept", auth_dept), + roles=vals["roles"], + ) + if not ok_modif: + H.append(tf_error_message(msg)) return "\n".join(H) + "\n" + tf[1] + F + if "date_expiration" in vals: + try: + if vals["date_expiration"]: + vals["date_expiration"] = datetime.datetime.strptime( + vals["date_expiration"], "%d/%m/%Y" + ) + if vals["date_expiration"] < datetime.datetime.now(): + H.append(tf_error_message("date expiration passée")) + return "\n".join(H) + "\n" + tf[1] + F + else: + vals["date_expiration"] = None + except ValueError: + H.append(tf_error_message("date expiration invalide")) + return "\n".join(H) + "\n" + tf[1] + F + if edit: # modif utilisateur (mais pas password ni user_name !) if (not can_choose_dept) and "dept" in vals: del vals["dept"] @@ -566,11 +598,14 @@ def create_user_form(user_name=None, edit=0, all_roles=False): vals["roles_string"] = ",".join(roles) # ok, edit - log(f"sco_users: editing {user_name} by {current_user.user_name}") - log(f"sco_users: previous_values={initvalues}") - log(f"sco_users: new_values={vals}") - sco_users.user_edit(user_name, vals) - flash(f"Utilisateur {user_name} modifié") + if not edit_only_roles: + log(f"sco_users: editing {user_name} by {current_user.user_name}") + log(f"sco_users: previous_values={initvalues}") + log(f"sco_users: new_values={vals}") + sco_users.user_edit(user_name, vals) + flash(f"Utilisateur {user_name} modifié") + else: + sco_users.user_edit(user_name, {"roles_string": vals["roles_string"]}) return flask.redirect( url_for( "users.user_info_page", @@ -946,14 +981,19 @@ def toggle_active_user(user_name: str = None): """Change active status of a user account""" if user_name is not None: # scodoc7func converti en int ! user_name = str(user_name) + u = User.query.filter_by(user_name=user_name).first() if not u: raise ScoValueError("invalid user_name") + # permission check: + if not ( + current_user.is_administrator() + or current_user.has_permission(Permission.ScoUsersAdmin, u.dept) + ): + raise ScoPermissionDenied() form = DeactivateUserForm() - if ( - request.method == "POST" and form.cancel.data - ): # if cancel button is clicked, the form.cancel.data will be True - # flash + if request.method == "POST" and form.cancel.data: + # if cancel button is clicked, the form.cancel.data will be True return redirect(url_for("users.index_html", scodoc_dept=g.scodoc_dept)) if form.validate_on_submit(): u.active = not u.active