def get_current_user(): """ Renvoie l'instance de l'utilisateur actuellement connecté. @return: Instance correspondant à l'utilisateur actuellement connecté ou None s'il n'est pas identifié. @rtype: L{User} ou None """ # Le plugin de méta-données SQLAlchemy (repoze.who.plugins.sa) # stocke directement l'instance de l'utilisateur dans l'identité. # Ce bout de code permet d'éviter une requête SQL supplémentaire. identity = request.environ.get('repoze.who.identity') if identity: user = identity.get('user') if user: return user # Pour les autres plugins. if request.identity is None: return None userid = request.identity.get('repoze.who.userid', None) if userid is None: return None return User.by_user_name(userid)
def add_metadata(self, environ, identity): """ Cette méthode n'ajoute pas de méta-données à proprement parler. À la place, elle crée un utilisateur dans la base de données si nécessaire, correspondant au contenu de la variable CGI C{REMOTE_USER} transmise par Apache. Dans le cas d'un identifiant Kerberos ("uid@REALM"), seule la partie "uid" est utilisée pour créer le compte. Pour cela, cette méthode effectue une requête à un annuaire LDAP. Elle génère en outre des groupes d'utilisateurs dans Vigilo correspondant aux groupes de l'utilisateur dans LDAP. Ces informations sont synchronisées à chaque requête HTTP ou bien une seule fois par session si un cache est utilisé (pour plus d'information, voir le paramètre C{cache_name} de L{VigiloLdapSync.__init__}). @param environ: Environnement de la requête HTTP en cours de traitement. @type environ: C{dict} @param identity: Identité de l'utilisateur qui tente d'accéder à l'application. @type identity: C{dict} """ remote_user_key = environ.get('repoze.who.remote_user_key') if not remote_user_key: return remote_user = environ.get(remote_user_key) if not remote_user: return remote_user = remote_user.decode(self.http_charset) logger = environ.get('repoze.who.logger') logger and logger.info(_('Remote user: %s'), remote_user) # Une identité Kerberos correspond à un "principal" # de la forme "uid@realm". On ne garde que l'uid. if '@' in remote_user: remote_user = remote_user.split('@', 1)[0] # On corrige l'identité trouvée par repoze.who afin que # les autres mdproviders puissent trouver une correspondance # dans la base de données. identity['repoze.who.userid'] = remote_user remote_user = unicode(remote_user) user = User.by_user_name(remote_user) if self.cache_name is not None: if 'beaker.session' not in environ: logger and logger.warning( _('Beaker must be present in the WSGI middleware ' 'stack for the cache to work')) # L'identité dans le cache doit être la même que celle # pour laquelle on est en train de s'authentifier. elif self.cache_name in environ['beaker.session'] and \ environ['beaker.session'][self.cache_name] == remote_user: return # On récupère les informations concernant l'utilisateur # pour alimenter / mettre à jour notre base de données. try: (user_fullname, user_email, user_groups) = \ self.retrieve_user_ldap_info(environ, remote_user) except: logger and logger.exception(_( 'Exception while contacting LDAP server')) return None if user_fullname is None: user_fullname = remote_user if user_groups is None: user_groups = [] # Création de l'utilisateur si nécessaire. if user is None: user = User( user_name=remote_user, fullname=user_fullname, email=user_email ) try: DBSession.add(user) DBSession.flush() logger and logger.info(_('New user created: %s'), remote_user) except SQLAlchemyError: transaction.abort() logger and logger.exception( _('Exception during user creation')) return None current_user_groups = user.usergroups # Suppression des groupes présents qui ne devraient plus l'être. for group in current_user_groups: if not group.group_name in user_groups: logger and logger.info( _('Removing user "%(user)s" from group "%(group)s"'), { 'user': remote_user, 'group': group.group_name, }) user.usergroups.remove(group) # Ajout des groupes manquants. for group_name in user_groups: try: # Cet appel provoque un flush implicite à la 2ème # itération, d'où le bloc try...except (cf. #909). group = UserGroup.by_group_name(group_name) except SQLAlchemyError: # Si une erreur s'est produite, on effectue un ROLLBACK # pour éviter de bloquer le thread avec l'erreur, mais # on continue tout de même car l'utilisateur a bien été # reconnu. transaction.abort() if 'beaker.session' in environ and self.cache_name is not None: environ['beaker.session'][self.cache_name] = remote_user environ['beaker.session'].save() return # Création des groupes au besoin. if group is None: logger and logger.info( _('Creating group "%s"'), group_name) group = UserGroup(group_name=group_name) DBSession.add(group) elif group in current_user_groups: continue logger and logger.info( _('Adding user "%(user)s" to group "%(group)s"'), { 'user': remote_user, 'group': group_name, }) user.usergroups.append(group) try: DBSession.flush() # Nécessaire afin que les modifications soient sauvegardées # en base de données. Sans cela, le groupe serait supprimé # automatiquement (via un ROLLBACK) en cas d'erreur issue # de l'application (status HTTP != 200). transaction.commit() transaction.begin() except SQLAlchemyError: transaction.abort() logger and logger.exception(_( 'Exception during groups creation')) return None if 'beaker.session' in environ and self.cache_name is not None: environ['beaker.session'][self.cache_name] = remote_user environ['beaker.session'].save() return
def test_getting_by_user_name(self): """Users should be fetcheable by their username""" him = User.by_user_name(u"foobar") eq_(him, self.obj)