Use non-destructive subconfigs instead of in-place per-root patching of config object
parent
44c5f2bb1a
commit
8b3d3363f2
|
@ -23,6 +23,7 @@ import vclib.ccvs
|
|||
import vclib.svn
|
||||
import cvsdb
|
||||
import viewvc
|
||||
import copy
|
||||
from viewvcmagic import ContentMagic
|
||||
|
||||
#########################################################################
|
||||
|
@ -143,6 +144,8 @@ class Config:
|
|||
|
||||
def __init__(self):
|
||||
self.__guesser = None
|
||||
self.__root_configs = {}
|
||||
self.__parent = None
|
||||
self.root_options_overlayed = 0
|
||||
for section in self._base_sections:
|
||||
if section[-1] == '*':
|
||||
|
@ -283,6 +286,34 @@ class Config:
|
|||
|
||||
return None
|
||||
|
||||
def get_root_config(self, rootname):
|
||||
"""Get configuration object with per-root overrides for 'rootname'"""
|
||||
if self.__parent:
|
||||
return self.__parent.get_root_config(rootname)
|
||||
elif rootname in self.__root_configs:
|
||||
return self.__root_configs[rootname]
|
||||
__guesser = self.__guesser
|
||||
__root_configs = self.__root_configs
|
||||
parser = self.parser
|
||||
self.parser = None
|
||||
self.__guesser = None
|
||||
self.__root_configs = None
|
||||
sub = copy.deepcopy(self)
|
||||
sub.parser = parser
|
||||
self.parser = parser
|
||||
self.__guesser = __guesser
|
||||
self.__root_configs = __root_configs
|
||||
self.__root_configs[rootname] = sub
|
||||
sub.__parent = self
|
||||
sub.overlay_root_options(rootname)
|
||||
return sub
|
||||
|
||||
def get_parent_config(self):
|
||||
"""Get the parent non-overridden config."""
|
||||
if self.__parent:
|
||||
return self.__parent
|
||||
return self
|
||||
|
||||
def overlay_root_options(self, rootname):
|
||||
"""Overlay per-root options for ROOTNAME atop the existing option
|
||||
set. This is a destructive change to the configuration."""
|
||||
|
@ -317,55 +348,6 @@ class Config:
|
|||
d[option] = parser.get(section, option)
|
||||
return d.items()
|
||||
|
||||
def get_authorizer_and_params_hack(self, rootname):
|
||||
"""Return a 2-tuple containing the name and parameters of the
|
||||
authorizer configured for use with ROOTNAME.
|
||||
|
||||
### FIXME: This whole thing is a hack caused by our not being able
|
||||
### to non-destructively overlay root options when trying to do
|
||||
### something like a root listing (which might need to get
|
||||
### different authorizer bits for each and every root in the list).
|
||||
### Until we have a good way to do that, we expose this function,
|
||||
### which assumes that base and per-vhost configuration has been
|
||||
### absorbed into this object and that per-root options have *not*
|
||||
### been overlayed. See issue #371."""
|
||||
|
||||
# We assume that per-root options have *not* been overlayed.
|
||||
assert(self.root_options_overlayed == 0)
|
||||
|
||||
if not self.conf_path:
|
||||
return None, {}
|
||||
|
||||
# Figure out the authorizer by searching first for a per-root
|
||||
# override, then falling back to the base/vhost configuration.
|
||||
authorizer = None
|
||||
root_options_section = 'root-%s/options' % (rootname)
|
||||
if self.parser.has_section(root_options_section) \
|
||||
and self.parser.has_option(root_options_section, 'authorizer'):
|
||||
authorizer = self.parser.get(root_options_section, 'authorizer')
|
||||
if not authorizer:
|
||||
authorizer = self.options.authorizer
|
||||
|
||||
# No authorizer? Get outta here.
|
||||
if not authorizer:
|
||||
return None, {}
|
||||
|
||||
# Dig up the parameters for the authorizer, starting with the
|
||||
# base/vhost items, then overlaying any root-specific ones we find.
|
||||
params = {}
|
||||
authz_section = 'authz-%s' % (authorizer)
|
||||
if hasattr(self, authz_section):
|
||||
sub_config = getattr(self, authz_section)
|
||||
for attr in dir(sub_config):
|
||||
params[attr] = getattr(sub_config, attr)
|
||||
root_authz_section = 'root-%s/authz-%s' % (rootname, authorizer)
|
||||
for section in self.parser.sections():
|
||||
if section == root_authz_section:
|
||||
for key, value in self._get_parser_items(self.parser, section):
|
||||
params[key] = value
|
||||
params['__config'] = self
|
||||
return authorizer, params
|
||||
|
||||
def get_authorizer_params(self, authorizer=None):
|
||||
"""Return a dictionary of parameter names and values which belong
|
||||
to the configured authorizer (or AUTHORIZER, if provided)."""
|
||||
|
|
|
@ -300,11 +300,10 @@ def is_forbidden(cfg, cvsroot_name, module):
|
|||
# the base and per-vhost configuration for authorizer and
|
||||
# authorizer parameters.
|
||||
if cvsroot_name:
|
||||
authorizer, params = cfg.get_authorizer_and_params_hack(cvsroot_name)
|
||||
else:
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
cfg = cfg.get_root_config(cvsroot_name)
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
# If CVSROOT_NAME isn't configured to use an authorizer, nothing
|
||||
# is forbidden. If it's configured to use something other than
|
||||
# the 'forbidden' authorizer, complain. Otherwise, check for
|
||||
|
|
|
@ -296,9 +296,11 @@ class Request:
|
|||
self.repos = rcr.repos
|
||||
self.rootpath = rcr.rootpath
|
||||
self.auth = rcr.auth
|
||||
|
||||
# Overlay root-specific options.
|
||||
cfg.overlay_root_options(self.rootname)
|
||||
|
||||
cfg = cfg.get_root_config(self)
|
||||
self.cfg = cfg
|
||||
|
||||
# Setup an Authorizer for this rootname and username
|
||||
debug.t_start('setup-authorizer')
|
||||
self.auth = setup_authorizer(cfg, self.username)
|
||||
|
@ -896,12 +898,12 @@ def setup_authorizer(cfg, username, rootname=None):
|
|||
"""Setup the authorizer. If ROOTNAME is provided, assume that
|
||||
per-root options have not been overlayed. Otherwise, assume they
|
||||
have (and fetch the authorizer for the configured root)."""
|
||||
|
||||
if rootname is None:
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
else:
|
||||
authorizer, params = cfg.get_authorizer_and_params_hack(rootname)
|
||||
|
||||
if rootname is not None:
|
||||
cfg = cfg.get_root_config(rootname)
|
||||
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
# No configured authorizer? No problem.
|
||||
if not authorizer:
|
||||
|
|
Loading…
Reference in New Issue