Mercurial > p > roundup > code
view frontends/ZRoundup/ZRoundup.py @ 6823:fe0091279f50
Refactor session db logging and key generation for sessions/otks
While I was working on the redis sessiondb stuff, I noticed that
log_wanrning, get_logger ... was duplicated. Also there was code to
generate a unique key for otks that was duplicated.
Changes:
creating new sessions_common.py and SessionsCommon class to provide
methods:
log_warning, log_info, log_debug, get_logger, getUniqueKey
getUniqueKey method is closer to the method used to make
session keys in client.py.
sessions_common.py now report when random_.py chooses a weak
random number generator. Removed same from rest.py.
get_logger reconciles all logging under
roundup.hyperdb.backends.<name of BasicDatabase class>
some backends used to log to root logger.
have BasicDatabase in other sessions_*.py modules inherit from
SessionCommon.
change logging to use log_* methods.
In addition:
remove unused imports reported by flake8 and other formatting
changes
modify actions.py, rest.py, templating.py to use getUniqueKey
method.
add tests for new methods
test_redis_session.py
swap out ModuleNotFoundError for ImportError to prevent crash in
python2 when redis is not present.
allow injection of username:password or just password into redis
connection URL. set pytest_redis_pw envirnment variable to password
or user:password when running test.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sun, 07 Aug 2022 01:51:11 -0400 |
| parents | 88dbacd11cd1 |
| children | fed0f839c260 |
line wrap: on
line source
# Copyright (c) 2001 Bizar Software Pty Ltd (http://www.bizarsoftware.com.au/) # This module is free software, and you may redistribute it and/or modify # under the same terms as Python, so long as this copyright message and # disclaimer are retained in their original form. # # IN NO EVENT SHALL BIZAR SOFTWARE PTY LTD BE LIABLE TO ANY PARTY FOR # DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING # OUT OF THE USE OF THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. # # BIZAR SOFTWARE PTY LTD SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, # BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS # FOR A PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # ''' ZRoundup module - exposes the roundup web interface to Zope This frontend works by providing a thin layer that sits between Zope and the regular CGI interface of roundup, providing the web frontend with the minimum of effort. This means that the regular CGI interface does all authentication quite independently of Zope. The roundup code is kept in memory though, and it runs in the same server as all your other Zope stuff, so it does have _some_ advantages over regular CGI :) ''' from roundup.anypy import urllib_ from Globals import InitializeClass, HTMLFile from OFS.SimpleItem import Item from OFS.PropertyManager import PropertyManager from Acquisition import Explicit, Implicit from Persistence import Persistent from AccessControl import ClassSecurityInfo from AccessControl import ModuleSecurityInfo modulesecurity = ModuleSecurityInfo() import roundup.instance from roundup.cgi import client modulesecurity.declareProtected('View management screens', 'manage_addZRoundupForm') manage_addZRoundupForm = HTMLFile('dtml/manage_addZRoundupForm', globals()) modulesecurity.declareProtected('Add Z Roundups', 'manage_addZRoundup') def manage_addZRoundup(self, id, instance_home, REQUEST): """Add a ZRoundup product """ # validate the instance_home roundup.instance.open(instance_home) self._setObject(id, ZRoundup(id, instance_home)) return self.manage_main(self, REQUEST) class RequestWrapper: '''Make the Zope RESPONSE look like a BaseHTTPServer ''' def __init__(self, RESPONSE): self.RESPONSE = RESPONSE self.wfile = self.RESPONSE def send_response(self, status): self.RESPONSE.setStatus(status) def send_header(self, header, value): self.RESPONSE.addHeader(header, value) def end_headers(self): # not needed - the RESPONSE object handles this internally on write() pass def start_response(self, headers, response): self.send_response(response) for key, value in headers: self.send_header(key, value) self.end_headers() class FormItem: '''Make a Zope form item look like a cgi.py one ''' def __init__(self, value): self.value = value if hasattr(self.value, 'filename'): self.filename = self.value.filename self.value = self.value.read() class FormWrapper: '''Make a Zope form dict look like a cgi.py one ''' def __init__(self, form): self.__form = form def __getitem__(self, item): entry = self.__form[item] if isinstance(entry, type([])): entry = list(map(FormItem, entry)) else: entry = FormItem(entry) return entry def __iter__(self): return iter(self.__form) def getvalue(self, key, default=None): if key in self.__form: return self.__form[key] else: return default def has_key(self, item): return item in self.__form def keys(self): return list(self.__form.keys()) def __repr__(self): return '<ZRoundup.FormWrapper %r>'%self.__form class ZRoundup(Item, PropertyManager, Implicit, Persistent): '''An instance of this class provides an interface between Zope and roundup for one roundup instance ''' meta_type = 'Z Roundup' security = ClassSecurityInfo() def __init__(self, id, instance_home): self.id = id self.instance_home = instance_home # define the properties that define this object _properties = ( {'id':'id', 'type': 'string', 'mode': 'w'}, {'id':'instance_home', 'type': 'string', 'mode': 'w'}, ) property_extensible_schema__ = 0 # define the tabs for the management interface manage_options= PropertyManager.manage_options + ( {'label': 'View', 'action':'index_html'}, ) + Item.manage_options icon = "misc_/ZRoundup/icon" security.declarePrivate('roundup_opendb') def roundup_opendb(self): '''Open the roundup instance database for a transaction. ''' tracker = roundup.instance.open(self.instance_home) request = RequestWrapper(self.REQUEST['RESPONSE']) env = self.REQUEST.environ # figure out the path components to set url = urllib_.urlparse( self.absolute_url() ) path = url[2] path_components = path.split( '/' ) # special case when roundup is '/' in this virtual host, if path == "/" : env['SCRIPT_NAME'] = "/" env['TRACKER_NAME'] = '' else : # all but the last element is the path env['SCRIPT_NAME'] = '/'.join( path_components[:-1] ) # the last element is the name env['TRACKER_NAME'] = path_components[-1] form = FormWrapper(self.REQUEST.form) if hasattr(tracker, 'Client'): return tracker.Client(tracker, request, env, form) return client.Client(tracker, request, env, form) security.declareProtected('View', 'index_html') def index_html(self): '''Alias index_html to roundup's index ''' # Redirect misdirected requests -- bugs 558867 , 565992 # PATH_INFO, as defined by the CGI spec, has the *real* request path orig_path = self.REQUEST.environ['PATH_INFO'] if orig_path[-1] != '/' : url = urllib_.urlparse( self.absolute_url() ) url = list( url ) # make mutable url[2] = url[2]+'/' # patch url = urllib_.urlunparse( url ) # reassemble RESPONSE = self.REQUEST.RESPONSE RESPONSE.setStatus( "MovedPermanently" ) # 301 RESPONSE.setHeader( "Location" , url ) return RESPONSE client = self.roundup_opendb() # fake the path that roundup should use client.split_path = ['index'] return client.main() def __getitem__(self, item): '''All other URL accesses are passed throuh to roundup ''' return PathElement(self, item).__of__(self) class PathElement(Item, Implicit): def __init__(self, zr, path): self.zr = zr self.path = path def __getitem__(self, item): ''' Get a subitem. ''' return PathElement(self.zr, self.path + '/' + item).__of__(self) def index_html(self, REQUEST=None): ''' Actually call through to roundup to handle the request. ''' try: client = self.zr.roundup_opendb() # fake the path that roundup should use client.path = self.path # and call roundup to do something client.main() return '' except client.NotFound: raise Exception('NotFound ' + REQUEST.URL) pass except: import traceback traceback.print_exc() # all other exceptions in roundup are valid raise InitializeClass(ZRoundup) modulesecurity.apply(globals()) # vim: set filetype=python ts=4 sw=4 et si
