1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
# -*- coding: utf-8 -*-
#
# Copyright (C) 2007-2008 Red Hat, Inc.
# This file is part of python-fedora
#
# python-fedora is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# python-fedora 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with python-fedora; if not, see <http://www.gnu.org/licenses/>
#
# Adapted from code in the TurboGears project licensed under the MIT license.
#
'''
This plugin provides integration with the Fedora Account System using JSON
calls to the account system server.
.. moduleauthor:: Toshio Kuratomi <tkuratom@redhat.com>
'''
import threading
from turbogears import config
from turbogears.visit.api import Visit, BaseVisitManager
from kitchen.text.converters import to_bytes
from fedora.client import FasProxyClient
from fedora import __version__
import logging
log = logging.getLogger("turbogears.identity.jsonfasvisit")
class JsonFasVisitManager(BaseVisitManager):
'''
This proxies visit requests to the Account System Server running remotely.
'''
fas_url = config.get('fas.url', 'https://admin.fedoraproject.org/accounts')
fas = None
debug = config.get('jsonfas.debug', False)
error_session_id = 0
error_session_id_lock = threading.Lock()
def __init__(self, timeout):
self.log = log
if not self.fas:
JsonFasVisitManager.fas = FasProxyClient(
self.fas_url,
debug=self.debug,
session_name=config.get('visit.cookie.name', 'tg-visit'),
useragent='JsonFasVisitManager/%s' % __version__,
retries=3
)
BaseVisitManager.__init__(self, timeout)
self.log.debug('JsonFasVisitManager.__init__: exit')
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):
'''
Return a new Visit object with the given key.
'''
self.log.debug('JsonFasVisitManager.new_visit_with_key: enter')
# Hit any URL in fas2 with the visit_key set. That will call the
# new_visit method in fas2
# We only need to get the session cookie from this request
try:
request_data = self.fas.refresh_session(visit_key)
except Exception:
# HACK -- if we get an error from calling FAS, we still need to
# return something to the application
try:
JsonFasVisitManager.error_session_id_lock.acquire()
session_id = str(JsonFasVisitManager.error_session_id)
JsonFasVisitManager.error_session_id += 1
finally:
JsonFasVisitManager.error_session_id_lock.release()
else:
session_id = request_data[0]
self.log.debug('JsonFasVisitManager.new_visit_with_key: exit')
return Visit(session_id, 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.
'''
self.log.debug('JsonFasVisitManager.visit_for_key: enter')
# Hit any URL in fas2 with the visit_key set. That will call the
# new_visit method in fas2
# We only need to get the session cookie from this request
try:
request_data = self.fas.refresh_session(visit_key)
except Exception:
# HACK -- if we get an error from calling FAS, we still need to
# return something to the application
try:
JsonFasVisitManager.error_session_id_lock.acquire()
session_id = str(JsonFasVisitManager.error_session_id)
JsonFasVisitManager.error_session_id += 1
finally:
JsonFasVisitManager.error_session_id_lock.release()
else:
session_id = request_data[0]
# 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 != session_id:
# # visit has expired
# return None
# # Hitting FAS has already updated the visit.
# return Visit(visit_key, False)
self.log.debug('JsonFasVisitManager.visit_for_key: exit')
if visit_key != session_id:
return Visit(session_id, True)
else:
return Visit(visit_key, False)
def update_queued_visits(self, queue):
'''Update the visit information on the server'''
self.log.debug(
'JsonFasVisitManager.update_queued_visits: %s' % len(queue))
# Hit any URL in fas with each visit_key to update the sessions
for visit_key in queue:
self.log.info('updating visit (%s)', to_bytes(visit_key))
try:
self.fas.refresh_session(visit_key)
except Exception:
# If fas returns an error, push the visit back onto the queue
try:
self.lock.acquire()
self.queue[visit_key] = queue[visit_key]
finally:
self.lock.release()
self.log.debug('JsonFasVisitManager.update_queued_visitsr exit')
|