def setUp(self): # loading the app self.appdir, self.config, self.auth = initenv() self.app = TestApp(make_app(self.config)) # adding a user if needed self.email = '*****@*****.**' % random.randint(1, 1000) self.user_name = extract_username(self.email) self.user = User(self.user_name) self.user_id = self.auth.get_user_id(self.user) self.password = '******' * 9 if self.user_id is None: self.auth.create_user(self.user_name, self.password, self.email) self.user_id = self.auth.get_user_id(self.user) # for the ldap backend, filling available_nodes if self.auth.__class__.__name__ == 'LDAPAuth': query = ('insert into available_nodes (node, ct, actives) values ' ' ("weave:localhost", 10, 10)') self.auth._engine.execute(query) try: self.nodes = load_and_configure(self.config, 'nodes') except KeyError: logger.debug(traceback.format_exc()) logger.debug("No node library in place") self.nodes = None try: self.reset = load_and_configure(self.config, 'reset_codes') except Exception: logger.debug(traceback.format_exc()) logger.debug("No reset code library in place") self.reset = None
def test_invariant(self): from services.tests.test_pluginreg import Dummy config = {'backend': 'services.tests.test_pluginreg.Dummy', 'foo': 'bar'} obj = load_and_configure(config) self.assertTrue(isinstance(obj, Dummy)) # second call, same config dict, should work obj = load_and_configure(config) self.assertTrue(isinstance(obj, Dummy))
def test_reset_code_sreg(self): try: import wsgi_intercept from wsgi_intercept.urllib2_intercept import install_opener install_opener() except ImportError: return def _fake_response(): return Response('0') def _no_email_response(): r = Response() r.status = '400 Bad Request' r.body = str(ERROR_NO_EMAIL_ADDRESS) return r config = {'backend': 'services.resetcodes.rc_sreg.ResetCodeSreg', 'sreg_location': 'localhost', 'sreg_path': '', 'sreg_scheme': 'http'} mgr = load_and_configure(config) user = User() user['userid'] = 1 user['username'] = '******' wsgi_intercept.add_wsgi_intercept('localhost', 80, _fake_response) self.assertRaises(AlreadySentError, mgr.generate_reset_code, user) wsgi_intercept.add_wsgi_intercept('localhost', 80, _no_email_response) self.assertRaises(NoEmailError, mgr.generate_reset_code, user)
def test_reset_code_sreg(self): try: import wsgi_intercept from wsgi_intercept.urllib2_intercept import install_opener install_opener() except ImportError: return def _fake_response(): return Response('0') def _no_email_response(): r = Response() r.status = '400 Bad Request' r.body = str(ERROR_NO_EMAIL_ADDRESS) return r config = { 'backend': 'services.resetcodes.rc_sreg.ResetCodeSreg', 'sreg_location': 'localhost', 'sreg_path': '', 'sreg_scheme': 'http' } mgr = load_and_configure(config) user = User() user['userid'] = 1 user['username'] = '******' wsgi_intercept.add_wsgi_intercept('localhost', 80, _fake_response) self.assertRaises(AlreadySentError, mgr.generate_reset_code, user) wsgi_intercept.add_wsgi_intercept('localhost', 80, _no_email_response) self.assertRaises(NoEmailError, mgr.generate_reset_code, user)
def test_reset_code_sql(self): config = { 'backend': 'services.resetcodes.rc_sql.ResetCodeSQL', 'sqluri': 'sqlite:///:memory:', 'create_tables': True, 'expiration': 1 } storage = load_and_configure(config) self._tests(storage) def _no_result(*args, **kwargs): class NoRows(object): def __init__(self): self.rowcount = 0 return NoRows() import services.resetcodes.rc_sql as rc_sql old_safe = rc_sql.safe_execute rc_sql.safe_execute = _no_result user = User() user['userid'] = 1 self.assertRaises(BackendError, storage.generate_reset_code, user, True) rc_sql.safe_execute = old_safe
def test_backenderrors(self): # this test makes sure all BackendErrors in user/sreg # give useful info in the TB if not CAN_MOCK_WSGI: raise SkipTest try: import ldap # NOQA except ImportError: # no ldap module means sreg_config won't load raise SkipTest mgr = load_and_configure(sreg_config) def _kill(): return HTTPServiceUnavailable() tarek = User('tarek') credentials = {"username": "******", "password": "******"} with mock_wsgi(_kill): try: mgr.delete_user(tarek, credentials) except BackendError, err: res = str(err)
def __init__(self, app): self.app = app self.logger = self.app.logger self.strict_usernames = app.config.get('auth.strict_usernames', True) self.shared_secret = app.config.get('global.shared_secret') self.auth = self.app.auth.backend # Fail noisily if not used with a new-style auth backend. try: is_newstyle_auth = isinstance(self.auth, ServicesUser) except Exception: is_newstyle_auth = False if not is_newstyle_auth: msg = "This code will only work with new-style auth backends."\ " Please set 'auth.backend' to a class from the"\ " services.user package." raise ValueError(msg) try: self.reset = load_and_configure(app.config, 'reset_codes') except Exception: # Have they not configured one, or did it fail to load? if 'reset_codes.backend' not in app.config: self.logger.debug("No reset code library in place") else: self.logger.debug(traceback.format_exc()) self.logger.debug("Reset code library failed to load") self.reset = None # For large-scale deployments you may want to use a dedicated # node-assigment server. See here for the details: # http://hg.mozilla.org/services/server-node-assignment try: self.nodes = load_and_configure(app.config, 'nodes') except Exception: # Have they not configured one, or did it fail to load? if 'nodes.backend' not in app.config: self.logger.debug("No node assignment library in place") else: self.logger.debug(traceback.format_exc()) self.logger.debug("Node assignment library failed to load") self.nodes = None # For simple deployments, a single fixed node will suffice. self.fallback_node = \ self.clean_location(app.config.get('nodes.fallback_node'))
def test_user_sql(self): try: import sqlalchemy # NOQA except ImportError: raise SkipTest self._tests(load_and_configure(sql_config)) if os.path.exists(TEMP_DATABASE_FILE): os.unlink(TEMP_DATABASE_FILE)
def test_user_sql(self): try: import sqlalchemy # NOQA except ImportError: raise SkipTest self._tests(load_and_configure(sql_config)) if os.path.exists("/tmp/test.db"): os.unlink("/tmp/test.db")
def test_reset_code_memcache(self): if check_memcache() is False: raise SkipTest() config = {'backend': 'services.resetcodes.rc_memcache.ResetCodeMemcache', 'nodes': ['127.0.0.1:11211'], 'debug': 1, 'expiration': 1} self._tests(load_and_configure(config))
def test_reset_code_memcache(self): if check_memcache() is False: raise SkipTest() config = { 'backend': 'services.resetcodes.rc_memcache.ResetCodeMemcache', 'nodes': ['127.0.0.1:11211'], 'debug': 1, 'expiration': 1 } self._tests(load_and_configure(config))
def setUp(self): if not MEMCACHED: raise SkipTest # Ensure we have metlog loaded so the timers will work. config_file = os.path.join(os.path.dirname(__file__), "sync.conf") config = Config(cfgfile=config_file) load_and_configure(config, "metlog_loader") fd, self.dbfile = mkstemp() os.close(fd) self.fn = 'syncstorage.storage.memcachedsql.MemcachedSQLStorage' kwds = self.STORAGE_CONFIG.copy() kwds['sqluri'] = 'sqlite:///%s' % self.dbfile self.storage = SyncStorage.get(self.fn, **kwds) # make sure we have the standard collections in place for name in ('client', 'crypto', 'forms', 'history'): self.storage.set_collection(_UID, name)
def test_user_ldap(self): try: import ldap # NOQA user1 = User() user1['username'] = '******' mgr = load_and_configure(ldap_config) credentials = {"username": "******", "password": "******"} mgr.authenticate_user(user1, credentials) except Exception: # we probably don't have an LDAP configured here. Don't test raise SkipTest self._tests(mgr)
def __init__(self, app): self.app = app self.strict_usernames = app.config.get('auth.strict_usernames', True) self.shared_secret = app.config.get('global.shared_secret') self.auth = self.app.auth.backend self.fallback_node = \ self.clean_location(app.config.get('nodes.fallback_node')) try: self.reset = load_and_configure(app.config, 'reset_codes') except Exception: logger.debug(traceback.format_exc()) logger.debug("No reset code library in place") self.reset = None
def test_load_direct(self): from services.tests.test_pluginreg import Dummy bad_config = Config({'backend': 'xxx'}) good_config = Config({'test.backend': 'services.tests.test_pluginreg.Dummy', 'test.foo': 'bar'}) self.assertRaises(KeyError, load_and_configure, bad_config) obj = load_and_configure(good_config, 'test') self.assertTrue(isinstance(obj, Dummy)) self.assertTrue(obj.foo == 'bar') missing_interface = {'interface': 'services.tests.test_pluginreg.Nope'} bad_interface = {'backend': 'services.tests.test_pluginreg.ImplementsBadly', 'interface': 'services.tests.test_pluginreg.ClassInterface'} good_interface = {'backend': 'services.tests.test_pluginreg.ImplementsCorrectly', 'interface': 'services.tests.test_pluginreg.ClassInterface'} obj = load_and_configure(good_interface) self.assertTrue(isinstance(obj, ImplementsCorrectly)) self.assertRaises(TypeError, load_and_configure, bad_interface) self.assertRaises(ImportError, load_and_configure, missing_interface)
def test_user_proxy(self): if not CAN_MOCK_WSGI: raise SkipTest mgr = load_and_configure(proxy_config) # Test for successful authentication whoami_was_called = [] def _successful_response(): whoami_was_called.append(True) return Response('{"userid": 42, "syncNode": "blah"}') user = User("test1") with mock_wsgi(_successful_response): userid = mgr.authenticate_user(user, "password") self.assertTrue(whoami_was_called) self.assertEquals(userid, 42) self.assertEquals(user["userid"], 42) # Test that we call the whoami API each time, no caching etc. del whoami_was_called[:] user = User("test1") with mock_wsgi(_successful_response): userid = mgr.authenticate_user(user, "password") self.assertTrue(whoami_was_called) self.assertEquals(userid, 42) self.assertEquals(user["userid"], 42) # Test unsuccessful authentication. del whoami_was_called[:] def _unsuccessful_response(): whoami_was_called.append(True) return Response(status=401) user = User("test1") with mock_wsgi(_unsuccessful_response): userid = mgr.authenticate_user(user, "wrongpassword") self.assertTrue(whoami_was_called) self.assertEquals(userid, None)
def test_user_sreg(self): if not CAN_MOCK_WSGI: raise SkipTest try: import ldap # NOQA except ImportError: # we probably don't have an LDAP configured here. Don't test raise SkipTest credentials = {"username": "******", "password": "******"} def _fake_response(): return Response('0') def _username_response(): return Response('"user1"') def _user_exists_response(): r = Response() r.status = '400 Bad Request' r.body = str(ERROR_INVALID_WRITE) return r mgr = load_and_configure(sreg_config) with mock_wsgi(_username_response): user1 = mgr.create_user('user1', 'password1', '*****@*****.**') self.assertEquals(user1['username'], 'user1') with mock_wsgi(_fake_response): self.assertTrue(mgr.admin_update_password(user1, 'newpass', 'key')) self.assertTrue(mgr.delete_user(user1, credentials)) with mock_wsgi(_user_exists_response): self.assertFalse(mgr.create_user('user1', 'password1', '*****@*****.**'))
def test_reset_code_sql(self): config = {'backend': 'services.resetcodes.rc_sql.ResetCodeSQL', 'sqluri': 'sqlite:///:memory:', 'create_tables': True, 'expiration': 1} storage = load_and_configure(config) self._tests(storage) def _no_result(*args, **kwargs): class NoRows(object): def __init__(self): self.rowcount = 0 return NoRows() import services.resetcodes.rc_sql as rc_sql old_safe = rc_sql.safe_execute rc_sql.safe_execute = _no_result user = User() user['userid'] = 1 self.assertRaises(BackendError, storage.generate_reset_code, user, True) rc_sql.safe_execute = old_safe
def __init__(self, config): # Load the auth backend if specified. # There may not be one configured if repoze.who is going to look # elsewhere for credentials, e.g. in a htpasswd database. self.config = config try: self.backend = load_and_configure(self.config, 'auth') except KeyError: self.backend = None self.logger = CLIENT_HOLDER.default_client # Extract who-related settings from the config or from our defaults. # the configured authentication backend. who_settings = self._get_who_settings(self.config) # Build up a who.ini config file in memory. # Any settings of the form "A.B.C = X" get translated into # a config file section like "[A:B]\nC = X" who_ini_lines = [] for key, value in who_settings.iteritems(): try: section, var = key.rsplit(".", 1) except ValueError: pass else: section = section.replace(".", ":") who_ini_lines.append("[%s]" % (section,)) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig("") parser.parse("\n".join(who_ini_lines)) self._api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Give all backend plugins access to the config. self._configure_backend_plugins(self._api_factory)
def __init__(self, config): # Load the auth backend if specified. # There may not be one configured if repoze.who is going to look # elsewhere for credentials, e.g. in a htpasswd database. self.config = config try: self.backend = load_and_configure(self.config, 'auth') except KeyError: self.backend = None self.logger = CLIENT_HOLDER.default_client # Extract who-related settings from the config or from our defaults. # the configured authentication backend. who_settings = self._get_who_settings(self.config) # Build up a who.ini config file in memory. # Any settings of the form "A.B.C = X" get translated into # a config file section like "[A:B]\nC = X" who_ini_lines = [] for key, value in who_settings.iteritems(): try: section, var = key.rsplit(".", 1) except ValueError: pass else: section = section.replace(".", ":") who_ini_lines.append("[%s]" % (section, )) who_ini_lines.append("%s = %s" % (var, value)) # Now we can parse that config using repoze.who's own machinery. parser = WhoConfig("") parser.parse("\n".join(who_ini_lines)) self._api_factory = APIFactory(parser.identifiers, parser.authenticators, parser.challengers, parser.mdproviders, parser.request_classifier, parser.challenge_decider) # Give all backend plugins access to the config. self._configure_backend_plugins(self._api_factory)
def __init__(self, urls, controllers, config=None, auth_class=None): self.mapper = Mapper() if config is None: self.config = Config() elif isinstance(config, Config): self.config = config else: # try to convert to config object self.config = Config(config) # global config self.retry_after = self.config.get('global.retry_after', 1800) # heartbeat page self.heartbeat_page = self.config.get('global.heartbeat_page', '__heartbeat__') # debug page, if any self.debug_page = self.config.get('global.debug_page') # check if we want to clean when the app ends self.sigclean = self.config.get('global.clean_shutdown', True) self.modules = dict() for module in self.config.get('app.modules', []): self.modules[module] = load_and_configure(self.config, module) # XXX: this should be converted to auto-load in self.modules # loading the authentication tool self.auth = None if auth_class is None else auth_class(self.config) # loading and connecting controllers self.controllers = dict([(name, klass(self)) for name, klass in controllers.items()]) for url in urls: if len(url) == 4: verbs, match, controller, action = url extras = {} elif len(url) == 5: verbs, match, controller, action, extras = url else: msg = "Each URL description needs 4 or 5 elements. Got %s" \ % str(url) raise ValueError(msg) if isinstance(verbs, str): verbs = [verbs] self.mapper.connect(None, match, controller=controller, action=action, conditions=dict(method=verbs), **extras) # loads host-specific configuration self._host_configs = {} # heartbeat & debug pages self.standard_controller = StandardController(self) # rehooked overridable points so they can be overridden in the base app self.standard_controller._debug_server = self._debug_server self.standard_controller._check_server = self._check_server # hooking callbacks when the app shuts down self.killing = self.shutting = False self.graceful_shutdown_interval = self.config.get( 'global.graceful_shutdown_interval', 1.) self.hard_shutdown_interval = self.config.get( 'global.hard_shutdown_interval', 1.) if self.sigclean: signal.signal(signal.SIGTERM, self._sigterm) signal.signal(signal.SIGINT, self._sigterm)
def __init__(self, ini_path=None, ini_dir=None, load_sections=None): """ :param ini_dir: Directory path in which to start looking for the ini file. Will climb the file tree from here looking for 'tests.ini' file, unless 'WEAVE_TESTFILE' env var is set, in which case it will climb the file tree from here looking for 'tests_${WEAVE_TESTFILE}.ini'. :param ini_path: Full path to configuration file. Takes precedence over ini_dir, if both are provided. Raises IOError if file doesn't exist. One or the other of `ini_dir` or `ini_path` arguments MUST be provided. :param load_sections: A sequence of strings that name the configuration sections that should be dynamically loaded. Any entry in this sequence could alternately be a 2-tuple containing the name of the section and the corresponding class parameter value to use. """ self.start_dir = ini_dir if ini_path: if not os.path.isfile(ini_path): raise IOError("invalid config file: %s" % ini_path) ini_dir = os.path.dirname(ini_path) elif ini_dir: if 'WEAVE_TESTFILE' in os.environ: test_filename = 'tests_%s.ini' % os.environ['WEAVE_TESTFILE'] else: test_filename = 'tests.ini' while True: ini_path = os.path.join(ini_dir, test_filename) if os.path.exists(ini_path): break if ini_path == ("/%s" % test_filename) \ or ini_path == test_filename: raise IOError("cannot locate %s" % test_filename) ini_dir = os.path.split(ini_dir)[0] else: raise ValueError('No ini_path or ini_dir specified.') self.ini_dir = ini_dir self.ini_path = ini_path ini_cfg = RawConfigParser() ini_cfg.read(ini_path) # loading loggers self.config = self.convert_config(ini_cfg, ini_path) # Ensure that metlog is available, either from the config # or by setting up a default client. try: loader = load_and_configure(self.config, "metlog_loader") client = loader.default_client except KeyError: sender = DebugCaptureSender() client = MetlogClient(sender, "syncserver") CLIENT_HOLDER.set_client(client.logger, client) if not hasattr(client, "cef"): log_cef_fn = metlog_cef.cef_plugin.config_plugin(dict()) client.add_method(log_cef_fn) if load_sections is not None: for section in load_sections: if isinstance(section, tuple): self.add_class(section[0], cls_param=section[1]) else: self.add_class(section)
def test_user_memory(self): self._tests(load_and_configure(memory_config))
def add_class(self, section, cls_param="backend"): """Takes the name of a config section and uses it to instantiate a class and put it into the env at self.[name]""" setattr(self, section, load_and_configure(self.config, section, cls_param))
def get_message_backend(config): print config return load_and_configure(config, 'messagestorage')
def test_user_proxycache(self): if not CAN_MOCK_WSGI: raise SkipTest mgr = load_and_configure(proxycache_config) # Check if memcache is up and running try: mgr._cache_get('test') except BackendError: raise SkipTest # We can authenticate a proper user from a cold cache, # by pulling their data from the proxy server. whoami_was_called = [] def _successful_response(): whoami_was_called.append(True) return Response('{"userid": 42, "syncNode": "blah"}') user = User("test1") with mock_wsgi(_successful_response): userid = mgr.authenticate_user(user, "password", ["syncNode"]) self.assertEquals(userid, 42) self.assertEquals(user["userid"], 42) self.assertEquals(user["syncNode"], "blah") self.assertTrue(whoami_was_called) # Subsequent authentication attempts will use the local cache. del whoami_was_called[:] user = User("test1") with mock_wsgi(_successful_response): userid = mgr.authenticate_user(user, "password", ["syncNode"]) self.assertEquals(userid, 42) self.assertEquals(user["userid"], 42) self.assertEquals(user["syncNode"], "blah") self.assertFalse(whoami_was_called) # Eventually the cache will expire. time.sleep(1) del whoami_was_called[:] user = User("test1") with mock_wsgi(_successful_response): userid = mgr.authenticate_user(user, "password", ["syncNode"]) self.assertEquals(userid, 42) self.assertEquals(user["userid"], 42) self.assertEquals(user["syncNode"], "blah") self.assertTrue(whoami_was_called) # Warm cache + bad password = authentication fails. # A different password will cause it to fall through to the proxy. def _unsuccessful_response(): whoami_was_called.append(True) return Response(status=401) del whoami_was_called[:] user = User("test1") with mock_wsgi(_unsuccessful_response): userid = mgr.authenticate_user(user, "wrongpassword") self.assertEquals(userid, None) self.assertTrue(whoami_was_called) # Cold cache + bad password = authentication fails. # Switch to a different username so that the cache is cold. del whoami_was_called[:] user = User("test2") with mock_wsgi(_unsuccessful_response): userid = mgr.authenticate_user(user, "password") self.assertEquals(userid, None) self.assertTrue(whoami_was_called) # The failed auth should not populate the cache. del whoami_was_called[:] user = User("test2") with mock_wsgi(_unsuccessful_response): userid = mgr.authenticate_user(user, "password") self.assertEquals(userid, None) self.assertTrue(whoami_was_called)
def __init__(self, config): self.config = config self.backend = load_and_configure(self.config, 'auth') self.logger = CLIENT_HOLDER.default_client
def __init__(self, config): self.config = config self.backend = load_and_configure(self.config, 'auth')
def __init__(self, urls, controllers, config=None, auth_class=None): self.mapper = Mapper() if config is None: self.config = Config() elif isinstance(config, Config): self.config = config else: # try to convert to config object self.config = Config(config) # global config self.retry_after = self.config.get('global.retry_after', 1800) # heartbeat page self.heartbeat_page = self.config.get('global.heartbeat_page', '__heartbeat__') # debug page, if any self.debug_page = self.config.get('global.debug_page') # check if we want to clean when the app ends self.sigclean = self.config.get('global.clean_shutdown', True) # load the specified plugin modules self.modules = dict() app_modules = self.config.get('app.modules', []) if isinstance(app_modules, basestring): app_modules = [app_modules] for module in app_modules: self.modules[module] = load_and_configure(self.config, module) if self.modules.get('metlog_loader') is not None: # stash the metlog client in a more convenient spot self.logger = self.modules.get('metlog_loader').default_client else: # there was no metlog config, default to using StdLibLoggingSender sender = StdLibLoggingSender('syncserver', json_types=[]) metlog = MetlogClient(sender, 'syncserver') CLIENT_HOLDER.set_client(metlog.logger, metlog) self.logger = metlog if not hasattr(self.logger, "cef"): log_cef_fn = metlog_cef.cef_plugin.config_plugin(dict()) self.logger.add_method(log_cef_fn) # XXX: this should be converted to auto-load in self.modules # loading the authentication tool self.auth = None if auth_class is None else auth_class(self.config) # loading and connecting controllers self.controllers = dict([(name, klass(self)) for name, klass in controllers.items()]) for url in urls: if len(url) == 4: verbs, match, controller, action = url extras = {} elif len(url) == 5: verbs, match, controller, action, extras = url else: msg = "Each URL description needs 4 or 5 elements. Got %s" \ % str(url) raise ValueError(msg) if isinstance(verbs, str): verbs = [verbs] # wrap action methods w/ metlog decorators controller_instance = self.controllers.get(controller) if controller_instance is not None: wrapped_name = '_%s_wrapped' % action method = getattr(controller_instance, action, None) if ((method is not None) and (not hasattr(controller_instance, wrapped_name))): # add wrapped method wrapped = svc_timeit(method) wrapped = incr_count(wrapped) wrapped = send_services_data(wrapped) setattr(controller_instance, wrapped_name, wrapped) self.mapper.connect(None, match, controller=controller, action=action, conditions=dict(method=verbs), **extras) # loads host-specific configuration self._host_configs = {} # heartbeat & debug pages self.standard_controller = StandardController(self) # rehooked overridable points so they can be overridden in the base app self.standard_controller._debug_server = self._debug_server self.standard_controller._check_server = self._check_server # hooking callbacks when the app shuts down self.killing = self.shutting = False self.graceful_shutdown_interval = self.config.get( 'global.graceful_shutdown_interval', 1.) self.hard_shutdown_interval = self.config.get( 'global.hard_shutdown_interval', 1.) if self.sigclean: signal.signal(signal.SIGTERM, self._sigterm) signal.signal(signal.SIGINT, self._sigterm)
def get_message_backend(config): return load_and_configure(config, cls_param = "notifserver.backend")
def get_message_notify(config): return load_and_configure(config, cls_param = "notifserver.notify")