From 08c5abdd49908527b11cc831507a45bb8b9ede31 Mon Sep 17 00:00:00 2001 From: Gaetan Delannay Date: Sun, 17 Jan 2010 22:01:14 +0100 Subject: [PATCH] Added the possibility to list logged users. --- gen/plone25/installer.py | 36 ++++++++++++++++++++++++++++++- gen/plone25/mixins/ToolMixin.py | 25 +++++++++++++++++++++ gen/plone25/templates/__init__.py | 1 + 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/gen/plone25/installer.py b/gen/plone25/installer.py index 20ef16d..559623d 100644 --- a/gen/plone25/installer.py +++ b/gen/plone25/installer.py @@ -2,7 +2,7 @@ Plone product.''' # ------------------------------------------------------------------------------ -import os, os.path +import os, os.path, time from StringIO import StringIO from sets import Set import appy @@ -397,6 +397,12 @@ class PloneInstaller: # Call custom installer if any if hasattr(self.appyTool, 'install'): self.tool.executeAppyAction('install', reindex=False) + # Patch the "logout" action with a custom Appy one that updates the + # list of currently logged users. + for action in site.portal_membership._actions: + if action.id == 'logout': + action.setActionExpression( + 'string:${portal_url}/%s/logout' % self.toolInstanceName) # Replace Plone front-page with an application-specific page if needed if self.appFrontPage: frontPageName = self.productName + 'FrontPage' @@ -447,6 +453,22 @@ class PloneInstaller: self.log("Uninstallation of %s done." % self.productName) return self.toLog.getvalue() +# Stuff for tracking user activity --------------------------------------------- +loggedUsers = {} +originalTraverse = None +doNotTrack = ('.jpg','.gif','.png','.js','.class','.css') + +def traverseWrapper(self, path, response=None, validated_hook=None): + '''This function is called every time a users gets a URL, this is used for + tracking user activity. self is a BaseRequest''' + res = originalTraverse(self, path, response, validated_hook) + t = time.time() + if os.path.splitext(path)[-1].lower() not in doNotTrack: + # Do nothing when the user gets non-pages + userId = self['AUTHENTICATED_USER'].getId() + if userId: loggedUsers[userId] = t + return res + # ------------------------------------------------------------------------------ class ZopeInstaller: '''This Zope installer runs every time Zope starts and encounters this @@ -494,6 +516,17 @@ class ZopeInstaller: constructors = (constructors[i],), permission = self.addContentPermissions[className]) + def enableUserTracking(self): + '''Enables the machinery allowing to know who is currently logged in. + Information about logged users will be stored in RAM, in the variable + named loggedUsers defined above.''' + global originalTraverse + if not originalTraverse: + # User tracking is not enabled yet. Do it now. + BaseRequest = self.ploneStuff['BaseRequest'] + originalTraverse = BaseRequest.traverse + BaseRequest.traverse = traverseWrapper + def finalizeInstallation(self): '''Performs some final installation steps.''' # Apply customization policy if any @@ -505,5 +538,6 @@ class ZopeInstaller: self.installApplication() self.installTool() self.installTypes() + self.enableUserTracking() self.finalizeInstallation() # ------------------------------------------------------------------------------ diff --git a/gen/plone25/mixins/ToolMixin.py b/gen/plone25/mixins/ToolMixin.py index 8796d78..eb6eaf8 100644 --- a/gen/plone25/mixins/ToolMixin.py +++ b/gen/plone25/mixins/ToolMixin.py @@ -724,4 +724,29 @@ class ToolMixin(AbstractMixin): text = self.translate('%s_list_%s' % (appyType['label'], v)) res.append((v, self.truncate(text, 30))) return res + + def logout(self): + '''Logs out the current user when he clicks on "disconnect".''' + rq = self.REQUEST + userId = self.portal_membership.getAuthenticatedMember().getId() + # Perform the logout in acl_users + try: + self.acl_users.logout(rq) + except: + pass + skinvar = self.portal_skins.getRequestVarname() + path = '/' + self.absolute_url(1) + if rq.has_key(skinvar) and not self.portal_skins.getCookiePersistence(): + rq.RESPONSE.expireCookie(skinvar, path=path) + # Invalidate existing sessions, but only if they exist. + sdm = self.session_data_manager + session = sdm.getSessionData(create=0) + if session is not None: + session.invalidate() + from Products.CMFPlone import transaction_note + transaction_note('Logged out') + # Remove user from variable "loggedUsers" + from appy.gen.plone25.installer import loggedUsers + if loggedUsers.has_key(userId): del loggedUsers[userId] + return self.goto(self.getParentNode().absolute_url()) # ------------------------------------------------------------------------------ diff --git a/gen/plone25/templates/__init__.py b/gen/plone25/templates/__init__.py index e4229c5..2a2195b 100644 --- a/gen/plone25/templates/__init__.py +++ b/gen/plone25/templates/__init__.py @@ -26,6 +26,7 @@ def countTest(): # ------------------------------------------------------------------------------ from config import * +from ZPublisher.HTTPRequest import BaseRequest import logging try: import CustomizationPolicy