from passlib.context import CryptContext from pyramid.settings import aslist password_context = CryptContext() def crypt_context_settings_to_string(settings, prefix='passlib.'): ''' returns a passlib context setting as a INI-formatted content :param dict settings: settings for the crypt context :param str prefix: prefix of the settings keys :rtype: (str) config string in INI format for CryptContext.load() This looks at first like a dump hack, but the parsing of all possible context settings is quite a task. Since passlib has a context parser included, this seems the most reliable way to do it. ''' as_list_keys = {'schemes', 'deprecated'} config_lines = ['[passlib]'] for ini_key, value in settings.items(): if ini_key.startswith(prefix): context_key = ini_key.replace(prefix, '') # the pyramid .ini format is different on lists # than the .ini format used by passlib. if context_key in as_list_keys and ',' not in value: value = ','.join(aslist(value)) config_lines.append(f'{context_key} = {value}') return '\n'.join(config_lines) def includeme(config): ''' initializing authentication, authorization and password hash settings Activate this setup using ``config.include('ordr2.security')``. ''' settings = config.get_settings() # configure the passlib context manager for hashing user passwords config_str = crypt_context_settings_to_string(settings, prefix='passlib.') password_context.load(config_str)