diff --git a/app/auth/models.py b/app/auth/models.py index a769a592b..e4ae2fc17 100644 --- a/app/auth/models.py +++ b/app/auth/models.py @@ -32,7 +32,7 @@ class User(UserMixin, db.Model): 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) + active = db.Column(db.Boolean, default=True, index=True) password_hash = db.Column(db.String(128)) last_seen = db.Column(db.DateTime, default=datetime.utcnow) @@ -48,6 +48,7 @@ class User(UserMixin, db.Model): def __init__(self, **kwargs): self.roles = [] + self.user_roles = [] super(User, self).__init__(**kwargs) if ( not self.roles @@ -78,6 +79,8 @@ class User(UserMixin, db.Model): """Check given password vs current one. Returns `True` if the password matched, `False` otherwise. """ + if not self.active: # inactived users can't login + return False if not self.password_hash: # user without password can't login return False return check_password_hash(self.password_hash, password) @@ -99,30 +102,29 @@ class User(UserMixin, db.Model): return return User.query.get(id) - def to_dict(self, include_email=False): + def to_dict(self, include_email=True): data = { "date_expiration": self.date_expiration.isoformat() + "Z" if self.date_expiration - else None, + else "", "date_modif_passwd": self.date_modif_passwd.isoformat() + "Z" if self.date_modif_passwd - else None, + else "", "date_created": self.date_created.isoformat() + "Z" if self.date_created - else None, - "dept": self.dept, + else "", + "dept": (self.dept or "").encode("utf-8"), # sco8 "id": self.id, - "is_old": self.is_old, - "status_txt": "(ancien)" if self.is_old else "", + "active": self.active, + "status_txt": "actif" if self.active else "fermé", "last_seen": self.last_seen.isoformat() + "Z", - "nom": self.nom, - "prenom": self.prenom, - "roles": self.roles, + "nom": (self.nom or "").encode("utf-8"), # sco8 + "prenom": (self.prenom or "").encode("utf-8"), # sco8 "roles_string": self.get_roles_string(), - "user_name": self.user_name, + "user_name": self.user_name.encode("utf-8"), # sco8 } if include_email: - data["email"] = self.email + data["email"] = self.email or "" return data def from_dict(self, data, new_user=False): @@ -154,12 +156,14 @@ class User(UserMixin, db.Model): # Permissions management: def has_permission(self, perm, dept=False): """Check if user has permission `perm` in given `dept`. - Emulate Zope `has_permission`` + Similar to Zope ScoDoc7 `has_permission`` Args: perm: integer, one of the value defined in Permission class. dept: dept id (eg 'RT') """ + if not self.active: + return False if dept is False: dept = g.scodoc_dept # les role liés à ce département, et les roles avec dept=None (super-admin) @@ -201,7 +205,7 @@ class User(UserMixin, db.Model): return ", ".join("{r.role.name}{r.dept}".format(r=r) for r in self.user_roles) def is_administrator(self): - return self.has_permission(Permission.ScoSuperAdmin, None) + return self.active and self.has_permission(Permission.ScoSuperAdmin, None) class AnonymousUser(AnonymousUserMixin): diff --git a/app/decorators.py b/app/decorators.py index 720bd4e75..0fe4f46c3 100644 --- a/app/decorators.py +++ b/app/decorators.py @@ -142,7 +142,7 @@ def scodoc7func(context): return func(*args, **kwargs) # if "scodoc_dept" in kwargs: - g.scodoc_dept = kwargs["scodoc_dept"] + g.scodoc_dept = kwargs["scodoc_dept"].encode("utf-8") # sco8 del kwargs["scodoc_dept"] elif not hasattr(g, "scodoc_dept"): g.scodoc_dept = None diff --git a/app/scodoc/ZScoUsers.py b/app/scodoc/ZScoUsers.py deleted file mode 100644 index a8418ed47..000000000 --- a/app/scodoc/ZScoUsers.py +++ /dev/null @@ -1,1314 +0,0 @@ -# -*- mode: python -*- -# -*- coding: utf-8 -*- - -############################################################################## -# -# Gestion scolarite IUT -# -# 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 -# -############################################################################## - -""" Gestion des utilisateurs (table SQL pour Zope User Folder) -""" -import string -import re -import time -import md5 -import base64 -import jaxml - -from app.scodoc.sco_zope import * # pylint: disable=unused-wildcard-import - -# --------------- -import app.scodoc.sco_utils as scu -import app.scodoc.notesdb as ndb -from app.scodoc.notes_log import log -from app.scodoc.scolog import logdb -from scolars import format_prenom, format_nom -from app.scodoc import sco_import_users -from app.scodoc import sco_excel -from app.scodoc.TrivialFormulator import TrivialFormulator, TF, tf_error_message -from app.scodoc.gen_tables import GenTable -from app.scodoc import sco_etud -from app.scodoc import sco_cache -from app.scodoc import sco_users - -from app.scodoc.sco_exceptions import ( - AccessDenied, - ScoException, - ScoValueError, - ScoInvalidDateError, - ScoLockedFormError, - ScoGenError, -) - -# --------------- -# cache global: chaque instance, repérée par son URL, a un cache -# qui est recréé à la demande -# On cache ici la liste des utilisateurs, pour une duree limitee -# (une minute). - -CACHE_userlist = {} - -# --------------- - - -class ZScoUsers( - ObjectManager, PropertyManager, RoleManager, Item, Persistent, Implicit -): - - "ZScousers object" - - meta_type = "ZScoUsers" - security = ClassSecurityInfo() - - # This is the list of the methods associated to 'tabs' in the ZMI - # Be aware that The first in the list is the one shown by default, so if - # the 'View' tab is the first, you will never see your tabs by cliquing - # on the object. - manage_options = ( - ({"label": "Contents", "action": "manage_main"},) - + PropertyManager.manage_options # add the 'Properties' tab - + ({"label": "View", "action": "index_html"},) - + Item.manage_options # add the 'Undo' & 'Owner' tab - + RoleManager.manage_options # add the 'Security' tab - ) - - # no permissions, only called from python - def __init__(self, id, title): - "initialise a new instance" - self.id = id - self.title = title - - # Connexion to SQL database of users: - - # Ugly but necessary during transition out of Zope: - _db_cnx_string = "dbname=SCOUSERS port=5432" - security.declareProtected("Change DTML Documents", "GetUsersDBConnexion") - GetUsersDBConnexion = ndb.GetUsersDBConnexion - - # -------------------------------------------------------------------- - # - # Users (top level) - # - # -------------------------------------------------------------------- - # used to view content of the object - security.declareProtected(ScoUsersView, "index_html") - - def index_html(self, REQUEST, all=0, with_olds=0, format="html"): - "gestion utilisateurs..." - all = int(all) - with_olds = int(with_olds) - # Controle d'acces - authuser = REQUEST.AUTHENTICATED_USER - user_name = str(authuser) - # log('user: %s roles: %s'%(user_name,authuser.getRolesInContext(self))) - user = self._user_list(args={"user_name": user_name}) - if not user: - zope_roles = authuser.getRolesInContext(self) - if ("Manager" in zope_roles) or ("manage" in zope_roles): - dept = "" # special case for zope admin - else: - raise AccessDenied("Vous n'avez pas la permission de voir cette page") - else: - dept = user[0]["dept"] - - H = [self.sco_header(REQUEST, page_title="Gestion des utilisateurs")] - H.append("
Ajouter un utilisateur' - ) - H.append( - ' Importer des utilisateurs
' - ) - if all: - checked = "checked" - else: - checked = "" - if with_olds: - olds_checked = "checked" - else: - olds_checked = "" - H.append( - """""" - % (REQUEST.URL0, checked, olds_checked) - ) - - L = self.list_users( - dept, - all=all, - with_olds=with_olds, - format=format, - REQUEST=REQUEST, - with_links=authuser.has_permission(Permission.ScoUsersAdmin, self), - ) - if format != "html": - return L - H.append(L) - - F = self.sco_footer(REQUEST) - return "\n".join(H) + F - - _userEditor = ndb.EditableTable( - "sco_users", - "user_id", - ( - "user_id", - "user_name", - "passwd", - "roles", - "date_modif_passwd", - "nom", - "prenom", - "email", - "dept", - "passwd_temp", - "status", - "date_expiration", - ), - output_formators={ - "date_modif_passwd": ndb.DateISOtoDMY, - "date_expiration": ndb.DateISOtoDMY, - }, - input_formators={ - "date_modif_passwd": ndb.DateDMYtoISO, - "date_expiration": ndb.DateDMYtoISO, - }, - sortkey="nom", - filter_nulls=False, - ) - - def _user_list(self, **kw): - # list info sur utilisateur(s) - cnx = self.GetUsersDBConnexion() - users = self._userEditor.list(cnx, **kw) - for u in users: - if u["status"] == "old": - u["status_txt"] = "(ancien)" - else: - u["status_txt"] = "" - - return users - - def _user_edit(self, user_name, vals): - # edit user - cnx = self.GetUsersDBConnexion() - vals["user_name"] = user_name - self._userEditor.edit(cnx, vals) - self.get_userlist_cache().inval_cache() # > - self.acl_users.cache_removeUser(user_name) # exUserFolder's caches - self.acl_users.xcache_removeUser(user_name) - # Ensure that if status is "old", login is disabled - # note that operation is reversible without having to re-enter a password - # We change the roles (to avoid dealing with passwd hash, controled by exUserFolder) - u = self._user_list(args={"user_name": user_name})[0] - if u["status"] == "old" and u["roles"] and u["roles"][0] != "-": - roles = ["-" + r for r in u["roles"].split(",")] - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - self.acl_users.scodoc_editUser(cursor, user_name, roles=roles) - self.get_userlist_cache().inval_cache() - elif not u["status"] and u["roles"] and u["roles"][0] == "-": - roles = [r[1:] for r in u["roles"].split(",") if (r and r[0] == "-")] - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - self.acl_users.scodoc_editUser(cursor, user_name, roles=roles) - self.get_userlist_cache().inval_cache() - - def _user_delete(self, user_name): - # delete user - cnx = self.GetUsersDBConnexion() - user_id = self._user_list(args={"user_name": user_name})[0]["user_id"] - self._userEditor.delete(cnx, user_id) - self.get_userlist_cache().inval_cache() # > - - def _all_roles(self): - "ensemble de tous les roles attribués ou attribuables" - roles = set(self.DeptUsersRoles()) - cnx = self.GetUsersDBConnexion() - L = self._userEditor.list(cnx, {}) - for l in L: - roles.update([x.strip() for x in l["roles"].split(",")]) - return [r for r in roles if r and r[0] != "-"] - - security.declareProtected(ScoUsersAdmin, "user_info") - - def user_info(self, user_name=None, user=None, format=None, REQUEST=None): - """Donne infos sur l'utilisateur (qui peut ne pas etre dans notre base). - Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict. - """ - if user_name: - infos = self._user_list(args={"user_name": user_name}) - else: - infos = [user.copy()] - user_name = user["user_name"] - - if not infos: - # special case: user is not in our database - return { - "user_name": user_name, - "nom": user_name, - "prenom": "", - "email": "", - "dept": "", - "nomprenom": user_name, - "prenomnom": user_name, - "prenom_fmt": "", - "nom_fmt": user_name, - "nomcomplet": user_name, - "nomplogin": user_name, - "nomnoacc": scu.suppress_accents(user_name), - "passwd_temp": 0, - "status": "", - "date_expiration": None, - } - else: - info = infos[0] - # always conceal password ! - del info["passwd"] # always conceal password ! - # - if info["prenom"]: - p = format_prenom(info["prenom"]) - else: - p = "" - if info["nom"]: - n = format_nom( - info["nom"], uppercase=False - ) # strcapitalize(strlower(info['nom'])) - else: - n = user_name - - prenom_abbrv = scu.abbrev_prenom(p) - # nomprenom est le nom capitalisé suivi de l'initiale du prénom - info["nomprenom"] = (n + " " + prenom_abbrv).strip() - # prenomnom est l'initiale du prénom suivie du nom - info["prenomnom"] = (prenom_abbrv + " " + n).strip() - # nom_fmt et prenom_fmt: minuscule capitalisé - info["nom_fmt"] = n - info["prenom_fmt"] = sco_etud.format_prenom(p) - # nomcomplet est le prenom et le nom complets - info["nomcomplet"] = info["prenom_fmt"] + " " + info["nom_fmt"] - # nomplogin est le nom en majuscules suivi du prénom et du login - # e.g. Dupont Pierre (dupont) - info["nomplogin"] = "%s %s (%s)" % (scu.strupper(n), p, info["user_name"]) - # nomnoacc est le nom en minuscules sans accents - info["nomnoacc"] = scu.suppress_accents(scu.strlower(info["nom"])) - - return scu.sendResult(REQUEST, info, name="user", format=format) - - def _can_handle_passwd(self, authuser, user_name, allow_admindepts=False): - """true if authuser can see or change passwd of user_name. - If allow_admindepts, allow Admin from all depts (so they can view users from other depts - and add roles to them). - authuser is a Zope user object. user_name is a string. - """ - # Is authuser a zope admin ? - zope_roles = authuser.getRolesInContext(self) - if ("Manager" in zope_roles) or ("manage" in zope_roles): - return True - # Anyone can change its own passwd (or see its informations) - if str(authuser) == user_name: - return True - # has permission ? - if not authuser.has_permission(Permission.ScoUsersAdmin, self): - return False - # Ok, now check that authuser can manage users from this departement - # Get user info - user = self._user_list(args={"user_name": user_name}) - if not user: - return False # we don't have infos on this user ! - # Get authuser info - auth_name = str(authuser) - authuser_info = self._user_list(args={"user_name": auth_name}) - if not authuser_info: - return False # not admin, and not in out database - auth_dept = authuser_info[0]["dept"] - if not auth_dept: - return True # if no dept, can access users from all depts ! - if auth_dept == user[0]["dept"] or allow_admindepts: - return True - else: - return False - - def do_change_password(self, user_name, password): - user = self._user_list(args={"user_name": user_name}) - assert len(user) == 1, "database inconsistency: len(user)=%d" % len(user) - # should not occur, already tested in _can_handle_passwd - cnx = self.GetUsersDBConnexion() # en mode autocommit - cursor = cnx.cursor(cursor_factory=ndb.ScoDocCursor) - cursor.execute( - "update sco_users set date_modif_passwd=now(), passwd_temp=0 where user_name=%(user_name)s", - {"user_name": user_name}, - ) - - # Laisse le exUserFolder modifier les donnees: - self.acl_users.scodoc_editUser( - cursor, user_name, password=password, roles=[user[0]["roles"]] - ) - - log("change_password: change ok for %s" % user_name) - self.get_userlist_cache().inval_cache() # > - - security.declareProtected(ScoView, "change_password") - - def change_password(self, user_name, password, password2, REQUEST): - "change a password" - # ScoUsersAdmin: modif tous les passwd de SON DEPARTEMENT - # sauf si pas de dept (admin global) - H = [] - F = self.sco_footer(REQUEST) - # Check access permission - if not self._can_handle_passwd(REQUEST.AUTHENTICATED_USER, user_name): - # access denied - log( - "change_password: access denied (authuser=%s, user_name=%s, ip=%s)" - % (REQUEST.AUTHENTICATED_USER, user_name, REQUEST.REMOTE_ADDR) - ) - raise AccessDenied( - "vous n'avez pas la permission de changer ce mot de passe" - ) - # check password - if password != password2: - H.append( - """Les deux mots de passes saisis sont différents !
- """ - % user_name - ) - else: - if not sco_users.is_valid_password(password): - H.append( - """ce mot de passe n\'est pas assez compliqué !
(oui, il faut un mot de passe vraiment compliqué !)
Ne notez pas ce mot de passe, mais mémorisez le !
Rappel: il est interdit de communiquer son mot de passe à un tiers, même si c'est un collègue de confiance !
Si vous n'êtes pas administrateur, le système va vous redemander votre login et nouveau mot de passe au prochain accès.
" - ) - return ( - """ - - - -Vous n'avez pas la permission de changer ce mot de passe
" - + F - ) - # - H.append( - """-
""" % (REQUEST.URL0, checked, olds_checked) ) @@ -137,7 +137,7 @@ def index_html(context, REQUEST, all_depts=False, with_olds=False, format="html" context, g.scodoc_dept, all_depts=all_depts, - with_olds=with_olds, + with_inactives=with_inactives, format=format, REQUEST=REQUEST, with_links=current_user.has_permission(Permission.ScoUsersAdmin, g.scodoc_dept), @@ -154,19 +154,19 @@ def list_users( context, dept, all_depts=False, # tous les departements - with_olds=False, # inclut les anciens utilisateurs (status "old") + with_inactives=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) + users = get_user_list(dept=dept, with_inactives=with_inactives) comm = "dept. %s" % dept.encode(scu.SCO_ENCODING) # sco8 else: - r = get_user_list(with_olds=with_olds) + r = get_user_list(with_inactives=with_inactives) comm = "tous" - if with_olds: + if with_inactives: comm += ", avec anciens" comm = "(" + comm + ")" # -- Add some information and links: @@ -180,7 +180,7 @@ def list_users( # Add links if with_links and can_modify: target = url_for( - "users.userinfo", scodoc_dept=g.scodoc_dept, user_name=u.user_name + "users.user_info_page", scodoc_dept=dept, user_name=u.user_name ).encode( scu.SCO_ENCODING ) # sco8 @@ -237,7 +237,7 @@ def list_users( ) -def get_user_list(dept=None, with_olds=False): +def get_user_list(dept=None, with_inactives=False): """Returns list of users. If dept, select users from this dept, else return all users. @@ -246,10 +246,170 @@ def get_user_list(dept=None, with_olds=False): 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() + if not with_inactives: + q = q.filter_by(active=True) + return q.order_by(User.nom, User.user_name).all() -# def get_user_infos(user_list): -# return [ user_info(u) for u in user_list ] +def _user_list(user_name): + "return user as a dict" + u = User.query.filter_by(user_name=user_name).first() + if u: + return u.to_dict() + else: + return None + + +def user_info(user_name=None, user=None): + """Donne infos sur l'utilisateur (qui peut ne pas etre dans notre base). + Si user_name est specifie, interroge la BD. Sinon, user doit etre un dict. + """ + if user_name: + info = _user_list(user_name) + else: + info = [user.copy()] + user_name = user["user_name"] + + if not info: + # special case: user is not in our database + return { + "user_name": user_name, + "nom": user_name, + "prenom": "", + "email": "", + "dept": "", + "nomprenom": user_name, + "prenomnom": user_name, + "prenom_fmt": "", + "nom_fmt": user_name, + "nomcomplet": user_name, + "nomplogin": user_name, + "nomnoacc": scu.suppress_accents(user_name), + "passwd_temp": 0, + "status": "", + "date_expiration": None, + } + else: + # Ensure we never publish password hash + if "password_hash" in info: + del info["password_hash"] + # + if info["prenom"]: + p = format_prenom(info["prenom"]) + else: + p = "" + if info["nom"]: + n = format_nom( + info["nom"], uppercase=False + ) # strcapitalize(strlower(info['nom'])) + else: + n = user_name + + prenom_abbrv = scu.abbrev_prenom(p) + # nomprenom est le nom capitalisé suivi de l'initiale du prénom + info["nomprenom"] = (n + " " + prenom_abbrv).strip() + # prenomnom est l'initiale du prénom suivie du nom + info["prenomnom"] = (prenom_abbrv + " " + n).strip() + # nom_fmt et prenom_fmt: minuscule capitalisé + info["nom_fmt"] = n + info["prenom_fmt"] = sco_etud.format_prenom(p) + # nomcomplet est le prenom et le nom complets + info["nomcomplet"] = info["prenom_fmt"] + " " + info["nom_fmt"] + # nomplogin est le nom en majuscules suivi du prénom et du login + # e.g. Dupont Pierre (dupont) + info["nomplogin"] = "%s %s (%s)" % (scu.strupper(n), p, info["user_name"]) + # nomnoacc est le nom en minuscules sans accents + info["nomnoacc"] = scu.suppress_accents(scu.strlower(info["nom"])) + + return info + + +def user_info_page(context, user_name=None, REQUEST=None): + """Display page of info about given user. + If user_name not specified, user current_user + """ + # 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( + context, + REQUEST, + page_title="Utilisateur %s" % user.user_name.encode("utf-8"), # sco8 + ) + ] + F = html_sco_header.sco_footer(context, REQUEST) + H.append("L' utilisateur '%s' n'est pas défini dans ce module.
" % user_name + ) + if user.has_permission(Permission.ScoEditAllNotes, dept): + H.append("(il peut modifier toutes les notes de %s)
" % dept) + if user.has_permission(Permission.ScoEditAllEvals, dept): + H.append("(il peut modifier toutes les évaluations de %s)
" % dept) + if user.has_permission(Permission.ScoImplement, dept): + H.append("(il peut creer des formations en %s)
" % dept) + else: + H.append( + """
+ Login : %(user_name)s
+ Nom : %(nom)s
+ Prénom : %(prenom)s
+ Mail : %(email)s
+ Roles : %(roles_string)s
+ Dept : %(dept)s
+ Dernière modif mot de passe: %(date_modif_passwd)s
+ Date d'expiration: %(date_expiration)s
+
Se déconnecter: logout
' + % url_for("auth.logout") + ) + # Liste des permissions + H.append( + ' ") + + if current_user.has_permission(Permission.ScoUsersAdmin, dept): + H.append( + '' + % url_for("users.index_html", scodoc_dept=g.scodoc_dept) + ) + return scu.sco8_join(H) + F diff --git a/app/scodoc/sco_utils.py b/app/scodoc/sco_utils.py index 0c9b6e449..ee025b07e 100644 --- a/app/scodoc/sco_utils.py +++ b/app/scodoc/sco_utils.py @@ -68,6 +68,12 @@ from app.scodoc.sco_codes_parcours import NOTES_TOLERANCE, CODES_EXPL from app.scodoc import sco_exceptions from app.scodoc import VERSION +# ----- TEMPORAIRE POUR MIGRATION SCODOC7 -> SCODOC8 avant python3 +def sco8_join(L, sep="\n"): # sco8 + return sep.join( + [x if not isinstance(x, types.UnicodeType) else x.encode("utf-8") for x in L] + ) + # ----- CALCUL ET PRESENTATION DES NOTES NOTES_PRECISION = 1e-4 # evite eventuelles erreurs d'arrondis diff --git a/app/views/users.py b/app/views/users.py index 456f62bd5..24a2899b2 100644 --- a/app/views/users.py +++ b/app/views/users.py @@ -35,7 +35,7 @@ Emmanuel Viennet, 2021 """ from flask import g -from flask import current_app +from flask import current_app, request from app.auth.models import Permission from app.auth.models import User @@ -45,9 +45,11 @@ from app.decorators import ( permission_required, admin_required, login_required, + ZRequest, ) from app.scodoc import sco_users +from app.scodoc import sco_utils as scu from app.views import users_bp as bp @@ -55,21 +57,28 @@ 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"): +def index_html(context, REQUEST, all_depts=False, with_inactives=False, format="html"): return sco_users.index_html( context, REQUEST=REQUEST, all_depts=all_depts, - with_olds=with_olds, + with_inactives=with_inactives, format=format, ) +@bp.route("/user_info") +@permission_required(Permission.ScoUsersView) +@scodoc7func(context) +def user_info(user_name, format="json", REQUEST=None): + info = sco_users.user_info(user_name=user_name) + return scu.sendResult(REQUEST, info, name="user", format=format) + + @bp.route("/create_user_form") def create_user_form(): raise NotImplementedError() @@ -80,6 +89,7 @@ def import_users_form(): raise NotImplementedError() -@bp.route("/userinfo") -def userinfo(): - raise NotImplementedError() +@bp.route("/user_info_page") +@scodoc7func(context) +def user_info_page(user_name, REQUEST=None): + return sco_users.user_info_page(context, user_name=user_name, REQUEST=REQUEST) diff --git a/scodoc_manager.py b/scodoc_manager.py index d3ed4d839..5cbadf34a 100644 --- a/scodoc_manager.py +++ b/scodoc_manager.py @@ -98,5 +98,5 @@ class FakeUsers(object): "date_expiration": None, } - def get_user_list(self, dept=None, with_olds=False): + def get_user_list(self, dept=None, with_inactives=False): return [self.user_info()]