def user_groups(self, userdn): """Get the groups the user belongs to. Given a user DN, return a sequence of LDAP attribute dictionaries matching the groups of which the DN is a member. If the DN does not exist, return ``None``. In a return value ``[(dn, attrdict), ...]``, ``dn`` will be the distinguished name of the group. Attrdict will be a dictionary mapping LDAP group attributes to sequences of values. If :meth:`pyramid.config.Configurator.ldap_set_groups_query` was not called, using this function will raise an :exc:`pyramid.exceptions.ConfiguratorError` """ search = getattr(self.registry, 'ldap_groups_query', None) if search is None: raise ConfigurationError( 'set_ldap_groups_query was not called during setup') login = re.match("^uid=(.*),.*$", userdn).groups()[0] with self.manager.connection() as conn: try: result = search.execute(conn, userdn=escape_for_search(userdn), login=login) except LDAPException: logger.debug('Exception in user_groups with userdn %r', userdn, exc_info=True) return None return result
def register(): directories = [] resolver = AssetResolver(self.package_name) # defer spec resolution until register to allow for asset # overrides to take place in an earlier config phase for spec in specs: # the trailing slash helps match asset overrides for folders if not spec.endswith('/'): spec += '/' asset = resolver.resolve(spec) directory = asset.abspath() if not asset.isdir(): raise ConfigurationError('"%s" is not a directory' % directory) intr = self.introspectable( 'translation directories', directory, spec, 'translation directory', ) intr['directory'] = directory intr['spec'] = spec introspectables.append(intr) directories.append(directory) tdirs = self.registry.queryUtility(ITranslationDirectories) if tdirs is None: tdirs = [] self.registry.registerUtility(tdirs, ITranslationDirectories) if override: tdirs.extend(directories) else: for directory in reversed(directories): tdirs.insert(0, directory)
def _get_resource(resource): parts = resource.split('/') if len(parts) == 2: bucket, collection = parts elif len(parts) == 5: _, _, bucket, _, collection = parts else: raise ConfigurationError(error_msg) valid_ids = (name_generator.match(bucket) and name_generator.match(collection)) if not valid_ids: raise ConfigurationError(error_msg) return { 'bucket': bucket, 'collection': collection }
def includeme(config): # pragma: no cover settings = config.registry.settings YEAR = 86400 * 365 config.add_directive('add_mgmt_view', add_mgmt_view, action_wrap=False) config.add_static_view('deformstatic', 'deform:static', cache_max_age=YEAR) config.add_static_view('sdistatic', 'substanced.sdi:static', cache_max_age=YEAR) # b/c alias for template lookups config.override_asset(to_override='substanced.sdi:templates/', override_with='substanced.sdi.views:templates/') manage_prefix = settings.get('substanced.manage_prefix', '/manage') manage_pattern = manage_prefix + '*traverse' config.add_route(MANAGE_ROUTE_NAME, manage_pattern) config.add_request_method(mgmt_path) config.add_request_method(mgmt_url) config.add_request_method(get_user, name='user', reify=True) config.add_request_method(FlashUndo, name='flash_with_undo', reify=True) config.include('deform_bootstrap') secret = settings.get('substanced.secret') if secret is None: raise ConfigurationError( 'You must set a substanced.secret key in your .ini file') session_factory = UnencryptedCookieSessionFactoryConfig(secret) config.set_session_factory(session_factory) from ..principal import groupfinder authn_policy = SessionAuthenticationPolicy(callback=groupfinder) authz_policy = ACLAuthorizationPolicy() config.set_authentication_policy(authn_policy) config.set_authorization_policy(authz_policy) config.add_permission('sdi.edit-properties') # used by property machinery
def get_beat_config(parser, section): get = partial(parser.get, section) has_option = partial(parser.has_option, section) schedule_type = get('type') schedule_value = safe_json(get, section, 'schedule') scheduler_cls = SCHEDULE_TYPE_MAP.get(schedule_type) if scheduler_cls is None: raise ConfigurationError('schedule type %s in section %s is invalid' % (schedule_type, section)) schedule = scheduler_cls(schedule_value) config = { 'task': get('task'), 'schedule': schedule, } if has_option('args'): config['args'] = safe_json(get, section, 'args') if has_option('kwargs'): config['kwargs'] = safe_json(get, section, 'kwargs') return config
def authtktauthenticationpolicy(_context, secret, callback=None, cookie_name='auth_tkt', secure=False, include_ip=False, timeout=None, reissue_time=None, max_age=None, http_only=False, path='/', wild_domain=True): try: policy = AuthTktAuthenticationPolicy(secret, callback=callback, cookie_name=cookie_name, secure=secure, include_ip=include_ip, timeout=timeout, reissue_time=reissue_time, max_age=max_age, http_only=http_only, path=path, wild_domain=wild_domain) except ValueError, why: # pragma: no cover raise ConfigurationError(str(why))
def parse_resource(resource): parts = resource.split('/') if len(parts) == 5: _, _, bucket, _, collection = parts else: raise ConfigurationError(ERROR_MSG % resource) return {'bucket': bucket, 'collection': collection}
def includeme(config): settings = config.registry.settings config.include('.models') # Security policies # a default authorization policy is mandatory authz_policy = ACLAuthorizationPolicy() config.set_authorization_policy(authz_policy) if not config.registry.queryUtility(IAuthenticationPolicy): config.set_authentication_policy(OauthAuthenticationPolicy()) auth_check = settings.get('oauth2_provider.auth_checker') if not auth_check: raise ConfigurationError( 'You must provide an implementation of the ' 'authentication check interface that is included with ' 'pyramid_oauth2_provider for verifying usernames and passwords') policy = config.maybe_dotted(auth_check) config.registry.registerUtility(policy, IAuthCheck) config.add_route('oauth2_provider_authorize', '/oauth2/authorize') config.add_route('oauth2_provider_token', '/oauth2/token') config.scan()
def authtktauthenticationpolicy(_context, secret, callback=None, cookie_name='auth_tkt', secure=False, include_ip=False, timeout=None, reissue_time=None, max_age=None, http_only=False, path='/', wild_domain=True): try: policy = AuthTktAuthenticationPolicy( secret, callback=callback, cookie_name=cookie_name, secure=secure, include_ip=include_ip, timeout=timeout, reissue_time=reissue_time, max_age=max_age, http_only=http_only, path=path, wild_domain=wild_domain, hashalg='sha512', ) except ValueError as why: # pragma: no cover raise ConfigurationError(str(why)) # authentication policies must be registered eagerly so they can # be found by the view registration machinery config = with_context(_context) set_authentication_policy(config, policy)
def includeme(config): config.add_api_capability( 'accounts', description='Manage user accounts.', url='https://kinto.readthedocs.io/en/latest/api/1.x/accounts.html') config.scan('kinto.plugins.accounts.views') PERMISSIONS_INHERITANCE_TREE[''].update({'account:create': {}}) PERMISSIONS_INHERITANCE_TREE['account'] = { 'write': { 'account': ['write'] }, 'read': { 'account': ['write', 'read'] } } # Add some safety to avoid weird behaviour with basicauth default policy. settings = config.get_settings() auth_policies = settings['multiauth.policies'] if 'basicauth' in auth_policies and 'account' in auth_policies: if auth_policies.index('basicauth') < auth_policies.index('account'): error_msg = ( "'basicauth' should not be mentioned before 'account' " "in 'multiauth.policies' setting.") raise ConfigurationError(error_msg)
def register_context(): bad_config = "" constructed_context = None try: if context: if isinstance(context, CryptContext): constructed_context = context else: msg = "'context' must be an instance of passlib.CryptContext" bad_config = msg elif ini_string: constructed_context = CryptContext.from_string(ini_string) elif ini_file: constructed_context = CryptContext.from_path(ini_file) elif context_dict: constructed_context = CryptContext(**context_dict) else: # no required arguments have been passed, error bad_config = 'requires a CryptContext or configuration data' except IOError: bad_config = "unable to open %s" % ini_file except ValueError: bad_config = "received invalid or incompatible configuration options" except KeyError: bad_config = "received unknown or forbidden configuration options" except TypeError: bad_config = "received configuration options of the wrong type" if bad_config: raise ConfigurationError("set_password_context %s" % bad_config) config.registry.password_context = constructed_context
def __init__(self, *args, **settings): if 'context' not in settings and len(args) > 0: exception, args = args[0], args[1:] settings['context'] = exception if len(args) > 0: raise ConfigurationError('unknown positional arguments') self.__dict__.update(settings)
def setup_storage(config): settings = config.get_settings() # Id generators by resource name. config.registry.id_generators = {} for key, value in settings.items(): m = re.match(r'^([^_]*)_?id_generator', key) if m is None: continue resource_name = m.group(1) id_generator = config.maybe_dotted(value) config.registry.id_generators[resource_name] = id_generator() storage_mod = settings['storage_backend'] if not storage_mod: return storage_mod = config.maybe_dotted(storage_mod) backend = storage_mod.load_from_config(config) if not isinstance(backend, storage.StorageBase): raise ConfigurationError("Invalid storage backend: %s" % backend) config.registry.storage = backend heartbeat = storage.heartbeat(backend) config.registry.heartbeats['storage'] = heartbeat
def register(): self._set_authentication_policy(policy) if self.registry.queryUtility(IAuthorizationPolicy) is None: raise ConfigurationError( 'Cannot configure an authentication policy without ' 'also configuring an authorization policy ' '(use the set_authorization_policy method)')
def http_cached_view(view, info): if info.settings.get('prevent_http_cache', False): return view seconds = info.options.get('http_cache') if seconds is None: return view options = {} if isinstance(seconds, (tuple, list)): try: seconds, options = seconds except ValueError: raise ConfigurationError( 'If http_cache parameter is a tuple or list, it must be ' 'in the form (seconds, options); not %s' % (seconds, )) def wrapper(context, request): response = view(context, request) prevent_caching = getattr(response.cache_control, 'prevent_auto', False) if not prevent_caching: response.cache_expires(seconds, **options) return response return wrapper
def __init__(self, **settings): if not settings.get('name'): raise ConfigurationError("You must provide a name for a viewlet") if 'for_' in settings: if settings.get('context') is None: settings['context'] = settings['for_'] self.__dict__.update(settings)
def includeme(config): """Add the Velruse standalone app configuration to a Pyramid app.""" settings = config.registry.settings config.add_directive('register_velruse_store', register_velruse_store) # setup application setup = settings.get('setup') or default_setup if setup: config.include(setup) # include supported providers for provider in settings_adapter: config.include('velruse.providers.%s' % provider) # configure requested providers for provider in find_providers(settings): load_provider(config, provider) # check for required settings if not settings.get('endpoint'): raise ConfigurationError('missing required setting "endpoint"') # add views config.add_view(auth_complete_view, context='velruse.AuthenticationComplete') config.add_view(auth_denied_view, context='velruse.AuthenticationDenied') config.add_view(auth_info_view, name='auth_info', request_param='format=json', renderer='json')
def __init__(self, val, config): self.orig = val try: val = re.compile(val) except re.error as why: raise ConfigurationError(why.args[0]) self.val = val
def user_groups(self, userdn): """ Given a user DN, return a sequence of LDAP attribute dictionaries matching the groups of which the DN is a member. If the DN does not exist, return ``None``. In a return value ``[(dn, attrdict), ...]``, ``dn`` will be the distinguished name of the group. Attrdict will be a dictionary mapping LDAP group attributes to sequences of values. The keys and values in the dictionary values provided will be decoded from UTF-8, recursively, where possible. The dictionary returned is a case-insensitive dictionary implemenation. If :meth:`pyramid.config.Configurator.ldap_set_groups_query` was not called, using this function will raise an :exc:`pyramid.exceptions.ConfiguratorError` """ with self.manager.connection() as conn: search = getattr(self.registry, 'ldap_groups_query', None) if search is None: raise ConfigurationError( 'set_ldap_groups_query was not called during setup') try: result = search.execute(conn, userdn=userdn) return _ldap_decode(result) except ldap.LDAPError: logger.debug('Exception in user_groups with userdn %r' % userdn, exc_info=True) return None
def prepare(request=None, registry=None): """ This function pushes data onto the Pyramid threadlocal stack (request and registry), making those objects 'current'. It returns a dictionary useful for bootstrapping a Pyramid application in a scripting environment. ``request`` is passed to the :app:`Pyramid` application root factory to compute the root. If ``request`` is None, a default will be constructed using the registry's :term:`Request Factory` via the :meth:`pyramid.interfaces.IRequestFactory.blank` method. If ``registry`` is not supplied, the last registry loaded from :attr:`pyramid.config.global_registries` will be used. If you have loaded more than one :app:`Pyramid` application in the current process, you may not want to use the last registry loaded, thus you can search the ``global_registries`` and supply the appropriate one based on your own criteria. The function returns a dictionary composed of ``root``, ``closer``, ``registry``, ``request`` and ``root_factory``. The ``root`` returned is the application's root resource object. The ``closer`` returned is a callable (accepting no arguments) that should be called when your scripting application is finished using the root. ``registry`` is the registry object passed or the last registry loaded into :attr:`pyramid.config.global_registries` if no registry is passed. ``request`` is the request object passed or the constructed request if no request is passed. ``root_factory`` is the root factory used to construct the root. """ if registry is None: registry = getattr(request, 'registry', global_registries.last) if registry is None: raise ConfigurationError('No valid Pyramid applications could be ' 'found, make sure one has been created ' 'before trying to activate it.') if request is None: request = _make_request('/', registry) threadlocals = {'registry': registry, 'request': request} threadlocal_manager.push(threadlocals) extensions = registry.queryUtility(IRequestExtensions) if extensions is not None: request._set_extensions(extensions) def closer(): threadlocal_manager.pop() root_factory = registry.queryUtility(IRootFactory, default=DefaultRootFactory) root = root_factory(request) if getattr(request, 'context', None) is None: request.context = root return { 'root': root, 'closer': closer, 'registry': registry, 'request': request, 'root_factory': root_factory }
def add_authn_plugin(self, config, plugin): plugin_id = plugin.get_id() if plugin_id in self._plugins.keys(): raise ConfigurationError( 'Cannot register authentication plugin twice: "%s"', plugin_id) else: log.debug('Register authentication plugin: "%s"', plugin_id) self._plugins[plugin_id] = plugin
def __call__(self, view): if (asyncio.iscoroutinefunction(view) or asyncio.iscoroutinefunction(getattr(view, '__call__', None)) or self.is_class_method_coroutine(view)): raise ConfigurationError( 'Coroutine {} mapped to executor.'.format(view)) view = super().__call__(view) return self.run_in_executor_view(view)
def get_uris(settings): named = [] for k, v in settings.items(): if k.startswith(NAMED): name = k[len(NAMED):] if not name: raise ConfigurationError( '%s is not a valid zodbconn identifier' % k) named.append((name, v)) primary = settings.get('zodbconn.uri') if primary is None and named: raise ConfigurationError( 'Must have primary zodbconn.uri in settings containing named uris') if primary: yield '', primary for name, uri in named: yield name, uri
def ensure(): if self.autocommit: return if self.registry.queryUtility(IAuthenticationPolicy) is None: raise ConfigurationError( 'Cannot configure an authorization policy without ' 'also configuring an authentication policy ' '(use the set_authorization_policy method)')
def __init__(self, val: List[str], config): if not val: raise ConfigurationError( "Excpected at least one value in headers predicate") self.sub_predicates = [ predicates.HeaderPredicate(subval, config) for subval in val ]
def initialize(config, version=None, settings_prefix='', default_settings=None): """Initialize kinto.core with the given configuration, version and project name. This will basically include kinto.core in Pyramid and set route prefix based on the specified version. :param config: Pyramid configuration :type config: ~pyramid:pyramid.config.Configurator :param str version: Current project version (e.g. '0.0.1') if not defined in application settings. :param str settings_prefix: Project name if not defined in application settings. :param dict default_settings: Override kinto.core default settings values. """ from kinto.core import DEFAULT_SETTINGS settings = config.get_settings() settings_prefix = settings.pop( 'kinto.settings_prefix', settings.get('settings_prefix')) or settings_prefix settings['settings_prefix'] = settings_prefix if not settings_prefix: warnings.warn('No value specified for `settings_prefix`') kinto_core_defaults = {**DEFAULT_SETTINGS} if default_settings: kinto_core_defaults.update(default_settings) load_default_settings(config, kinto_core_defaults) http_scheme = settings['http_scheme'] if http_scheme != 'https': warnings.warn('HTTPS is not enabled') # Override project version from settings. project_version = settings.get('project_version') or version if not project_version: error_msg = 'Invalid project version: {}'.format(project_version) raise ConfigurationError(error_msg) settings['project_version'] = project_version = str(project_version) # HTTP API version. http_api_version = settings.get('http_api_version') if http_api_version is None: # The API version is derivated from the module version if not provided. http_api_version = '.'.join(project_version.split('.')[0:2]) settings['http_api_version'] = http_api_version = str(http_api_version) api_version = 'v{}'.format(http_api_version.split('.')[0]) # Include kinto.core views with the correct api version prefix. config.include('kinto.core', route_prefix=api_version) config.route_prefix = api_version
def initialize(config, version=None, settings_prefix="", default_settings=None): """Initialize kinto.core with the given configuration, version and project name. This will basically include kinto.core in Pyramid and set route prefix based on the specified version. :param config: Pyramid configuration :type config: ~pyramid:pyramid.config.Configurator :param str version: Current project version (e.g. '0.0.1') if not defined in application settings. :param str settings_prefix: Project name if not defined in application settings. :param dict default_settings: Override kinto.core default settings values. """ from kinto.core import DEFAULT_SETTINGS settings = config.get_settings() settings_prefix = (settings.pop("kinto.settings_prefix", settings.get("settings_prefix")) or settings_prefix) settings["settings_prefix"] = settings_prefix if not settings_prefix: warnings.warn("No value specified for `settings_prefix`") kinto_core_defaults = {**DEFAULT_SETTINGS} if default_settings: kinto_core_defaults.update(default_settings) load_default_settings(config, kinto_core_defaults) http_scheme = settings["http_scheme"] if http_scheme != "https": warnings.warn("HTTPS is not enabled") # Override project version from settings. project_version = settings.get("project_version") or version if not project_version: error_msg = f"Invalid project version: {project_version}" raise ConfigurationError(error_msg) settings["project_version"] = project_version = str(project_version) # HTTP API version. http_api_version = settings.get("http_api_version") if http_api_version is None: # The API version is derivated from the module version if not provided. http_api_version = ".".join(project_version.split(".")[0:2]) settings["http_api_version"] = http_api_version = str(http_api_version) api_version = f"v{http_api_version.split('.')[0]}" # Include kinto.core views with the correct api version prefix. config.include("kinto.core", route_prefix=api_version) config.route_prefix = api_version
def add_translation_dirs(self, *specs): """ Add one or more :term:`translation directory` paths to the current configuration state. The ``specs`` argument is a sequence that may contain absolute directory paths (e.g. ``/usr/share/locale``) or :term:`asset specification` names naming a directory path (e.g. ``some.package:locale``) or a combination of the two. Example: .. code-block:: python config.add_translation_dirs('/usr/share/locale', 'some.package:locale') Later calls to ``add_translation_dir`` insert directories into the beginning of the list of translation directories created by earlier calls. This means that the same translation found in a directory added later in the configuration process will be found before one added earlier in the configuration process. However, if multiple specs are provided in a single call to ``add_translation_dirs``, the directories will be inserted into the beginning of the directory list in the order they're provided in the ``*specs`` list argument (items earlier in the list trump ones later in the list). """ directories = [] introspectables = [] for spec in specs[::-1]: # reversed package_name, filename = self._split_spec(spec) if package_name is None: # absolute filename directory = filename else: __import__(package_name) package = sys.modules[package_name] directory = os.path.join(package_path(package), filename) if not os.path.isdir(os.path.realpath(directory)): raise ConfigurationError('"%s" is not a directory' % directory) intr = self.introspectable('translation directories', directory, spec, 'translation directory') intr['directory'] = directory intr['spec'] = spec introspectables.append(intr) directories.append(directory) def register(): for directory in directories: tdirs = self.registry.queryUtility(ITranslationDirectories) if tdirs is None: tdirs = [] self.registry.registerUtility(tdirs, ITranslationDirectories) tdirs.insert(0, directory) self.action(None, register, introspectables=introspectables)
def _add_view_from_route(self, route_name, view, context, permission, renderer, attr, ): if view: self.add_view( permission=permission, context=context, view=view, name='', route_name=route_name, renderer=renderer, attr=attr, ) else: # prevent mistakes due to misunderstanding of how hybrid calls to # add_route and add_view interact if attr: raise ConfigurationError( 'view_attr argument not permitted without view ' 'argument') if context: raise ConfigurationError( 'view_context argument not permitted without view ' 'argument') if permission: raise ConfigurationError( 'view_permission argument not permitted without view ' 'argument') if renderer: raise ConfigurationError( 'view_renderer argument not permitted without ' 'view argument') warnings.warn( 'Passing view-related arguments to add_route() is deprecated as of ' 'Pyramid 1.1. Use add_view() to associate a view with a route ' 'instead. See "Deprecations" in "What\'s New in Pyramid 1.1" ' 'within the general Pyramid documentation for further details.', DeprecationWarning, 4)
def includeme(config): config.add_api_capability( 'accounts', description='Manage user accounts.', url='https://kinto.readthedocs.io/en/latest/api/1.x/accounts.html') config.scan('kinto.plugins.accounts.views') PERMISSIONS_INHERITANCE_TREE['root'].update({ 'account:create': {} }) PERMISSIONS_INHERITANCE_TREE['account'] = { 'write': {'account': ['write']}, 'read': {'account': ['write', 'read']} } # Add some safety to avoid weird behaviour with basicauth default policy. settings = config.get_settings() auth_policies = settings['multiauth.policies'] if 'basicauth' in auth_policies and 'account' in auth_policies: if auth_policies.index('basicauth') < auth_policies.index('account'): error_msg = ("'basicauth' should not be mentioned before 'account' " "in 'multiauth.policies' setting.") raise ConfigurationError(error_msg) # We assume anyone in account_create_principals is to create # accounts for other people. # No one can create accounts for other people unless they are an # "admin", defined as someone matching account_write_principals. # Therefore any account that is in account_create_principals # should be in account_write_principals too. creators = set(settings.get('account_create_principals', '').split()) admins = set(settings.get('account_write_principals', '').split()) cant_create_anything = creators.difference(admins) # system.Everyone isn't an account. cant_create_anything.discard('system.Everyone') if cant_create_anything: message = ('Configuration has some principals in account_create_principals ' 'but not in account_write_principals. These principals will only be ' 'able to create their own accounts. This may not be what you want.\n' 'If you want these users to be able to create accounts for other users, ' 'add them to account_write_principals.\n' 'Affected users: {}'.format(list(cant_create_anything))) raise ConfigurationError(message)