From f60b394cfe7b29e1677cb6d71d3391dab062f4ad Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 3 Mar 2008 14:31:04 -0800 Subject: [PATCH 1/2] Use cookieName from config. Move fasURL into a class variable from global. --- fas/fas/jsonfasprovider.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fas/fas/jsonfasprovider.py b/fas/fas/jsonfasprovider.py index 8b833aa..73c09b6 100644 --- a/fas/fas/jsonfasprovider.py +++ b/fas/fas/jsonfasprovider.py @@ -51,14 +51,15 @@ try: except NameError: from sets import Set as set, ImmutableSet as frozenset -FASURL = config.get('fas.url', 'https://admin.fedoraproject.org/admin/fas/') - class JsonFasIdentity(BaseClient): '''Associate an identity with a person in the auth system. ''' + cookieName = config.get('visit.cookie.name', 'tg-visit') + fasURL = config.get('fas.url', 'https://admin.fedoraproject.org/admin/fas/') + def __init__(self, visit_key, user=None, username=None, password=None, debug=False): - super(JsonFasIdentity, self).__init__(FASURL, debug=debug) + super(JsonFasIdentity, self).__init__(self.fasURL, debug=debug) if user: self._user = user self._groups = frozenset( @@ -74,7 +75,6 @@ class JsonFasIdentity(BaseClient): # Set the cookie to the user's tg_visit key before requesting # authentication. That way we link the two together. self._sessionCookie = Cookie.SimpleCookie() - self.cookieName = config.get('visit.cookie.name', 'tg-visit') self._sessionCookie[self.cookieName] = self.visit_key self.username = username self.password = password @@ -139,7 +139,7 @@ class JsonFasIdentity(BaseClient): ''' if not self.visit_key: return - # Call FASURL logout method + # Call Account System Server logout method self.send_request('logout', auth=True) class JsonFasIdentityProvider(object): From f60e9f162f7cc795e5b788f42a6fafd47926e82b Mon Sep 17 00:00:00 2001 From: Toshio Kuratomi Date: Mon, 3 Mar 2008 14:32:33 -0800 Subject: [PATCH 2/2] * Changes to client to enable visit tracking. Incidentally, makes better use of traffic to the db at the expense of data to the account server. * jsonfas visit manager. --- fas/fas/client.py | 16 ++++++-- fas/fas/jsonfasvisit.py | 82 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 3 deletions(-) create mode 100644 fas/fas/jsonfasvisit.py diff --git a/fas/fas/client.py b/fas/fas/client.py index 3b13981..36e18d1 100644 --- a/fas/fas/client.py +++ b/fas/fas/client.py @@ -177,9 +177,13 @@ class BaseClient(object): if auth: req.add_header('Cookie', self.session.output(attrs=[], - header='').strip()) + header='').strip()) + elif self._sessionCookie: + # If the cookie exists, send it so that visit tracking works. + req.add_header('Cookie', self._sessionCookie.output(attrs=[], + header='').strip()) try: - response = urllib2.urlopen(req).read() + response = urllib2.urlopen(req) except urllib2.HTTPError, e: if e.msg == 'Forbidden': if (inspect.currentframe().f_back.f_code != @@ -195,8 +199,14 @@ class BaseClient(object): log.error(e) raise ServerError, str(e) + # In case the server returned a new session cookie to us try: - data = simplejson.loads(response) + self._sessionCookie.load(response.headers['set-cookie']) + except KeyError: + pass + + try: + data = simplejson.load(response) except Exception, e: regex = re.compile('(.*)') match = regex.search(response) diff --git a/fas/fas/jsonfasvisit.py b/fas/fas/jsonfasvisit.py new file mode 100644 index 0000000..0bdd38a --- /dev/null +++ b/fas/fas/jsonfasvisit.py @@ -0,0 +1,82 @@ +''' +This plugin provides integration with the Fedora Account System using JSON +calls to the account system server. +''' + +import Cookie + +from datetime import datetime + +from sqlalchemy import * +from sqlalchemy.orm import class_mapper + +from turbogears import config +from turbogears.visit.api import BaseVisitManager, Visit +from turbogears.database import get_engine, metadata, session, mapper +from turbogears.util import load_class + +# Once this works, propogate the changes back to python-fedora and import as +# from fedora.tg.client import BaseClient +from client import BaseClient + +import gettext +t = gettext.translation('python-fedora', '/usr/share/locale', fallback=True) +_ = t.ugettext + +import logging +log = logging.getLogger("turbogears.identity.savisit") + +class JsonFasVisitManager(BaseClient): + ''' + This proxies visit requests to the Account System Server running remotely. + + We don't need to worry about threading and other concerns because our proxy + doesn't cause any asynchronous calls. + ''' + fasURL = config.get('fas.url', 'https://admin.fedoraproject.org/admin/fas') + cookieName = config.get('visit.cookie.name', 'tg-visit') + + def __init__(self, timeout, debug=None): + super(JsonFasVisitManager,self).__init__(self.fasURL, debug=debug) + + def create_model(self): + ''' + Create the Visit table if it doesn't already exist + ''' + # Not needed as the visit tables reside remotely in the FAS2 database. + pass + + def new_visit_with_key(self, visit_key): + # Hit any URL in fas2 with the visit_key set. That will call the + # new_visit method in fas2 + self._sessionCookie = Cookie.SimpleCookie() + self._sessionCookie[self.cookieName] = visit_key + data = self.send_request('', auth=True) + return Visit(self._sessionCookie[self.cookieName].value, True) + + def visit_for_key(self, visit_key): + ''' + Return the visit for this key or None if the visit doesn't exist or has + expired. + ''' + # Hit any URL in fas2 with the visit_key set. That will call the + # new_visit method in fas2 + self._sessionCookie = Cookie.SimpleCookie() + self._sessionCookie[self.cookieName] = visit_key + data = self.send_request('', auth=True) + # Knowing what happens in turbogears/visit/api.py when this is called, + # we can shortcircuit this step and avoid a round trip to the FAS + # server. + # if visit_key != self._sessionCookie[self.cookieName].value: + # # visit has expired + # return None + # # Hitting FAS has already updated the visit. + # return Visit(visit_key, False) + if visit_key != self._sessionCookie[self.cookieName].value: + return Visit(self._sessionCookie[self.cookieName].value, True) + else: + return Visit(visit_key, False) + + def update_queued_visits(self, queue): + # Let the visit_manager on the FAS server manage this + pass