Example #1
0
 def test_load_missing(self):
     config_path = os.path.join(self.colpath, "does_not_exist")
     config.load([(config_path, True)])
     with pytest.raises(Exception) as exc_info:
         config.load([(config_path, False)])
     e = exc_info.value
     assert "Failed to load config file %r" % config_path in str(e)
Example #2
0
    def __init__(self, **kwargs):

        configuration = config.load(extra_config=settings.RADICALE_CONFIG)
        logger = logging.getLogger("diary")

        super(DiaryView, self).__init__(configuration, logger)
        super(View, self).__init__(**kwargs)
Example #3
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.shutdown_socket, shutdown_socket_out = socket.socketpair()
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
         # Find available port
         sock.bind(("127.0.0.1", 0))
         self.sockname = sock.getsockname()
     self.configuration.update(
         {
             "storage": {
                 "filesystem_folder": self.colpath
             },
             "server": {
                 "hosts": "[%s]:%d" % self.sockname
             },
             # Enable debugging for new processes
             "logging": {
                 "level": "debug"
             },
             # Disable syncing to disk for better performance
             "internal": {
                 "filesystem_fsync": "False"
             }
         },
         "test",
         internal=True)
     self.thread = threading.Thread(target=server.serve,
                                    args=(self.configuration,
                                          shutdown_socket_out))
     ssl_context = ssl.create_default_context()
     ssl_context.check_hostname = False
     ssl_context.verify_mode = ssl.CERT_NONE
     self.opener = request.build_opener(
         request.HTTPSHandler(context=ssl_context), DisabledRedirectHandler)
Example #4
0
 def test_invalid_option_plugin(self):
     configuration = config.load()
     with pytest.raises(Exception) as exc_info:
         configuration.update({"auth": {"x": "x"}}, "test")
     e = exc_info.value
     assert "Invalid option 'x'" in str(e)
     assert "section 'auth'" in str(e)
Example #5
0
 def test_plugin_schema_duplicate_option(self):
     plugin_schema = {"auth": {"type": {"value": "False", "type": bool}}}
     configuration = config.load()
     with pytest.raises(Exception) as exc_info:
         configuration.copy(plugin_schema)
     e = exc_info.value
     assert "option already exists in 'auth': 'type'" in str(e)
Example #6
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["internal"]["filesystem_fsync"] = "False"
     self.application = Application(self.configuration)
Example #7
0
 def test_copy(self):
     configuration1 = config.load()
     configuration1.update({"server": {"max_connections": "1111"}}, "test")
     configuration2 = configuration1.copy()
     configuration2.update({"server": {"max_connections": "1112"}}, "test")
     assert configuration1.get("server", "max_connections") == 1111
     assert configuration2.get("server", "max_connections") == 1112
Example #8
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration.update({
         "storage": {"filesystem_folder": self.colpath},
         # Disable syncing to disk for better performance
         "internal": {"filesystem_fsync": "False"}}, "test", internal=True)
Example #9
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["internal"]["filesystem_fsync"] = "False"
     # Set incorrect authentication delay to a very low value
     self.configuration["auth"]["delay"] = "0.002"
Example #10
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["storage"]["filesystem_fsync"] = "False"
     # Required on Windows, doesn't matter on Unix
     self.configuration["storage"]["filesystem_close_lock_file"] = "True"
Example #11
0
 def test_plugin_schema_invalid(self):
     PLUGIN_SCHEMA = {"server": {"new_option": {"value": "False",
                                                "type": bool}}}
     configuration = config.load()
     with pytest.raises(Exception) as exc_info:
         configuration.copy(PLUGIN_SCHEMA)
     e = exc_info.value
     assert "not a plugin section: 'server" in str(e)
Example #12
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["internal"]["filesystem_fsync"] = "False"
     # Set incorrect authentication delay to a very low value
     self.configuration["auth"]["delay"] = "0.002"
Example #13
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["storage"]["filesystem_fsync"] = "False"
     # Required on Windows, doesn't matter on Unix
     self.configuration["storage"]["filesystem_close_lock_file"] = "True"
Example #14
0
 def test_internal(self):
     configuration = config.load()
     configuration.update({"internal": {"internal_server": "True"}}, "test",
                          internal=True)
     with pytest.raises(Exception) as exc_info:
         configuration.update(
             {"internal": {"internal_server": "True"}}, "test")
     e = exc_info.value
     assert "Invalid section 'internal'" in str(e)
Example #15
0
 def test_invalid_value(self):
     configuration = config.load()
     with pytest.raises(Exception) as exc_info:
         configuration.update({"server": {"max_connections": "x"}}, "test")
     e = exc_info.value
     assert "Invalid positive_int" in str(e)
     assert "option 'max_connections" in str(e)
     assert "section 'server" in str(e)
     assert "'x'" in str(e)
Example #16
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration.update({
         "storage": {"filesystem_folder": self.colpath},
         # Disable syncing to disk for better performance
         "internal": {"filesystem_fsync": "False"},
         # Set incorrect authentication delay to a very low value
         "auth": {"delay": "0.002"}}, "test", internal=True)
Example #17
0
 def test_load_multiple(self):
     config_path1 = self._write_config({
         "server": {"hosts": "192.0.2.1:1111"}}, "config1")
     config_path2 = self._write_config({
         "server": {"max_connections": 1111}}, "config2")
     configuration = config.load([(config_path1, False),
                                  (config_path2, False)])
     assert len(configuration.get("server", "hosts")) == 1
     assert configuration.get("server", "hosts")[0] == ("192.0.2.1", 1111)
     assert configuration.get("server", "max_connections") == 1111
Example #18
0
 def test_plugin_schema_option_invalid(self):
     PLUGIN_SCHEMA = {"auth": {}}
     configuration = config.load()
     configuration.update({"auth": {"type": "new_plugin",
                                    "new_option": False}}, "test")
     with pytest.raises(Exception) as exc_info:
         configuration.copy(PLUGIN_SCHEMA)
     e = exc_info.value
     assert "Invalid option 'new_option'" in str(e)
     assert "section 'auth'" in str(e)
Example #19
0
 def test_plugin_schema(self):
     PLUGIN_SCHEMA = {"auth": {"new_option": {"value": "False",
                                              "type": bool}}}
     configuration = config.load()
     configuration.update({"auth": {"type": "new_plugin"}}, "test")
     plugin_configuration = configuration.copy(PLUGIN_SCHEMA)
     assert plugin_configuration.get("auth", "new_option") is False
     configuration.update({"auth": {"new_option": "True"}}, "test")
     plugin_configuration = configuration.copy(PLUGIN_SCHEMA)
     assert plugin_configuration.get("auth", "new_option") is True
Example #20
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["storage"]["filesystem_fsync"] = "False"
     # Required on Windows, doesn't matter on Unix
     self.configuration["storage"]["filesystem_close_lock_file"] = "True"
     # Set incorrect authentication delay to a very low value
     self.configuration["auth"]["delay"] = "0.002"
Example #21
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["storage"]["filesystem_fsync"] = "False"
     # Required on Windows, doesn't matter on Unix
     self.configuration["storage"]["filesystem_close_lock_file"] = "True"
     # Set incorrect authentication delay to a very low value
     self.configuration["auth"]["delay"] = "0.002"
Example #22
0
 def setup(self):
     self.configuration = config.load()
     self.configuration.set("storage", "type", self.storage_type)
     self.logger = logging.getLogger("radicale_test")
     self.colpath = tempfile.mkdtemp()
     self.configuration.set("storage", "filesystem_folder", self.colpath)
     # Disable syncing to disk for better performance
     self.configuration.set("storage", "filesystem_fsync", "False")
     # Required on Windows, doesn't matter on Unix
     self.configuration.set("storage", "close_lock_file", "True")
     self.application = Application(self.configuration, self.logger)
Example #23
0
    def test_custom(self):
        """Custom authentication."""
        configuration = config.load()
        configuration.set("auth", "type", "tests.custom.auth")
        self.application = Application(configuration,
                                       logging.getLogger("radicale_test"))

        status, headers, answer = self.request(
            "GET", "/", HTTP_AUTHORIZATION="dG1wOmJlcG8=")
        assert status == 200
        assert "Radicale works!" in answer
Example #24
0
    def test_custom(self):
        """Custom authentication."""
        configuration = config.load()
        configuration.set("auth", "type", "tests.custom.auth")
        self.application = Application(
            configuration, logging.getLogger("radicale_test"))

        status, headers, answer = self.request(
            "GET", "/", HTTP_AUTHORIZATION="dG1wOmJlcG8=")
        assert status in (200, 303)
        assert "Radicale works!" in answer or "Redirected to .web/" in answer
Example #25
0
    def __init__(self, **kwargs):
        # radicale/__main__.py:
        # configuration = config.load(config_paths,
        #                             ignore_missing_paths=ignore_missing_paths)
        # serve(configuration, logger)

        configuration = config.load(extra_config=settings.DJRADICALE_CONFIG)
        logger = logging.getLogger('djradicale')

        super(DjRadicaleView, self).__init__(configuration, logger)
        super(View, self).__init__(**kwargs)
Example #26
0
 def setup(self):
     self.configuration = config.load()
     self.configuration.set("storage", "type", self.storage_type)
     self.logger = logging.getLogger("radicale_test")
     self.colpath = tempfile.mkdtemp()
     self.configuration.set("storage", "filesystem_folder", self.colpath)
     # Disable syncing to disk for better performance
     self.configuration.set("storage", "fsync", "False")
     # Required on Windows, doesn't matter on Unix
     self.configuration.set("storage", "close_lock_file", "True")
     self.application = Application(self.configuration, self.logger)
Example #27
0
def _init_application(config_path):
    global _application, _application_config_path
    with _application_lock:
        if _application is not None:
            return
        _application_config_path = config_path
        configuration = config.load([config_path] if config_path else [],
                                    ignore_missing_paths=False)
        filename = os.path.expanduser(configuration.get("logging", "config"))
        debug = configuration.getboolean("logging", "debug")
        logger = log.start("radicale", filename, debug)
        _application = Application(configuration, logger)
Example #28
0
def _init_application(config_path, wsgi_errors):
    global _application, _application_config_path
    with _application_lock:
        if _application is not None:
            return
        log.setup()
        with log.register_stream(wsgi_errors):
            _application_config_path = config_path
            configuration = config.load([config_path] if config_path else [],
                                        ignore_missing_paths=False)
            log.set_level(configuration.get("logging", "level"))
            _application = Application(configuration)
Example #29
0
def _init_application(config_path, wsgi_errors):
    global _application, _application_config_path
    with _application_lock:
        if _application is not None:
            return
        log.setup()
        with log.register_stream(wsgi_errors):
            _application_config_path = config_path
            configuration = config.load([config_path] if config_path else [],
                                        ignore_missing_paths=False)
            log.set_level(configuration.get("logging", "level"))
            _application = Application(configuration)
Example #30
0
 def test_privileged(self):
     configuration = config.load()
     configuration.update({"server": {
         "_internal_server": "True"
     }},
                          "test",
                          privileged=True)
     with pytest.raises(Exception) as exc_info:
         configuration.update({"server": {
             "_internal_server": "True"
         }}, "test")
     e = exc_info.value
     assert "Invalid option '_internal_server'" in str(e)
Example #31
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration.update(
         {
             "storage": {
                 "filesystem_folder": self.colpath,
                 # Disable syncing to disk for better performance
                 "_filesystem_fsync": "False"
             }
         },
         "test",
         privileged=True)
     self.application = Application(self.configuration)
Example #32
0
def _init_application(config_path, wsgi_errors):
    global _application, _application_config_path
    with _application_lock:
        if _application is not None:
            return
        log.setup()
        with log.register_stream(wsgi_errors):
            _application_config_path = config_path
            configuration = config.load(
                config.parse_compound_paths(config.DEFAULT_CONFIG_PATH,
                                            config_path))
            log.set_level(configuration.get("logging", "level"))
            # Inspect configuration after logger is configured
            configuration.inspect()
            _application = Application(configuration)
Example #33
0
def application(environ, start_response):
    global _application
    if _application is None:
        with _application_lock:
            if _application is None:
                config_paths = []
                if os.environ.get("RADICALE_CONFIG"):
                    config_paths.append(os.environ["RADICALE_CONFIG"])
                configuration = config.load(config_paths,
                                            ignore_missing_paths=False)
                filename = os.path.expanduser(configuration.get("logging",
                                                                "config"))
                debug = configuration.getboolean("logging", "debug")
                logger = log.start("radicale", filename, debug)
                _application = Application(configuration, logger)
    return _application(environ, start_response)
Example #34
0
def application(environ, start_response):
    global _application
    if _application is None:
        with _application_lock:
            if _application is None:
                config_paths = []
                if os.environ.get("RADICALE_CONFIG"):
                    config_paths.append(os.environ["RADICALE_CONFIG"])
                configuration = config.load(config_paths,
                                            ignore_missing_paths=False)
                filename = os.path.expanduser(
                    configuration.get("logging", "config"))
                debug = configuration.getboolean("logging", "debug")
                logger = log.start("radicale", filename, debug)
                _application = Application(configuration, logger)
    return _application(environ, start_response)
Example #35
0
def _init_application(config_path, wsgi_errors):
    global _application, _application_config_path
    with _application_lock:
        if _application is not None:
            return
        log.setup()
        with log.register_stream(wsgi_errors):
            _application_config_path = config_path
            configuration = config.load(
                config.parse_compound_paths(config.DEFAULT_CONFIG_PATH,
                                            config_path))
            log.set_level(configuration.get("logging", "level"))
            # Log configuration after logger is configured
            for source, miss in configuration.sources():
                logger.info("%s %s", "Skipped missing" if miss else "Loaded",
                            source)
            _application = Application(configuration)
Example #36
0
    def test_root(self):
        """Htpasswd authentication."""
        htpasswd_file_path = os.path.join(self.colpath, ".htpasswd")
        with open(htpasswd_file_path, "wb") as fd:
            fd.write(b"tmp:{SHA}" +
                     base64.b64encode(hashlib.sha1(b"bepo").digest()))

        configuration = config.load()
        configuration.set("auth", "type", "htpasswd")
        configuration.set("auth", "htpasswd_filename", htpasswd_file_path)
        configuration.set("auth", "htpasswd_encryption", "sha1")

        self.application = Application(configuration,
                                       logging.getLogger("radicale_test"))

        status, headers, answer = self.request(
            "GET", "/", HTTP_AUTHORIZATION="dG1wOmJlcG8=")
        assert status == 200
        assert "Radicale works!" in answer
Example #37
0
    def test_root(self):
        """Htpasswd authentication."""
        htpasswd_file_path = os.path.join(self.colpath, ".htpasswd")
        with open(htpasswd_file_path, "wb") as fd:
            fd.write(b"tmp:{SHA}" + base64.b64encode(
                hashlib.sha1(b"bepo").digest()))

        configuration = config.load()
        configuration.set("auth", "type", "htpasswd")
        configuration.set("auth", "htpasswd_filename", htpasswd_file_path)
        configuration.set("auth", "htpasswd_encryption", "sha1")

        self.application = Application(
            configuration, logging.getLogger("radicale_test"))

        status, headers, answer = self.request(
            "GET", "/", HTTP_AUTHORIZATION="dG1wOmJlcG8=")
        assert status in (200, 303)
        assert "Radicale works!" in answer or "Redirected to .web/" in answer
Example #38
0
def setup():
    """Set global logging up."""
    global register_stream
    handler = ThreadedStreamHandler()
    logging.basicConfig(format=LOGGER_FORMAT, datefmt=DATE_FORMAT,
                        handlers=[handler])
    register_stream = handler.register_stream
    log_record_factory = IdentLogRecordFactory(logging.getLogRecordFactory())
    logging.setLogRecordFactory(log_record_factory)

    """If a logfile is provided, also add a filehandler as logger"""
    configuration = config.load()
    logfile = configuration.get("logging", "logfile")

    if logfile:
        logfile_handler = logging.FileHandler(logfile, mode="w")
        logger.addHandler(logfile_handler)
        logger.info(f"Registered filelogger to {logfile}")
        
    set_level(logging.WARNING)
Example #39
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Enable debugging for new processes
     self.configuration["logging"]["level"] = "debug"
     # Disable syncing to disk for better performance
     self.configuration["internal"]["filesystem_fsync"] = "False"
     self.shutdown_socket, shutdown_socket_out = socket.socketpair()
     with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
         # Find available port
         sock.bind(("127.0.0.1", 0))
         self.sockname = sock.getsockname()
         self.configuration["server"]["hosts"] = "[%s]:%d" % self.sockname
     self.thread = threading.Thread(target=server.serve, args=(
         self.configuration, shutdown_socket_out))
     ssl_context = ssl.create_default_context()
     ssl_context.check_hostname = False
     ssl_context.verify_mode = ssl.CERT_NONE
     self.opener = request.build_opener(
         request.HTTPSHandler(context=ssl_context),
         DisabledRedirectHandler)
Example #40
0
def run():
    """Run Radicale as a standalone server."""
    # Get command-line arguments
    parser = argparse.ArgumentParser(usage="radicale [OPTIONS]")

    parser.add_argument("--version", action="version", version=VERSION)
    parser.add_argument("--verify-storage", action="store_true",
                        help="check the storage for errors and exit")
    parser.add_argument(
        "-C", "--config", help="use a specific configuration file")

    groups = {}
    for section, values in config.INITIAL_CONFIG.items():
        group = parser.add_argument_group(section)
        groups[group] = []
        for option, data in values.items():
            kwargs = data.copy()
            long_name = "--{0}-{1}".format(
                section, option.replace("_", "-"))
            args = kwargs.pop("aliases", [])
            args.append(long_name)
            kwargs["dest"] = "{0}_{1}".format(section, option)
            groups[group].append(kwargs["dest"])
            del kwargs["value"]
            if "internal" in kwargs:
                del kwargs["internal"]

            if kwargs["type"] == bool:
                del kwargs["type"]
                kwargs["action"] = "store_const"
                kwargs["const"] = "True"
                opposite_args = kwargs.pop("opposite", [])
                opposite_args.append("--no{0}".format(long_name[1:]))
                group.add_argument(*args, **kwargs)

                kwargs["const"] = "False"
                kwargs["help"] = "do not {0} (opposite of {1})".format(
                    kwargs["help"], long_name)
                group.add_argument(*opposite_args, **kwargs)
            else:
                group.add_argument(*args, **kwargs)

    args = parser.parse_args()
    if args.config is not None:
        config_paths = [args.config] if args.config else []
        ignore_missing_paths = False
    else:
        config_paths = ["/etc/radicale/config",
                        os.path.expanduser("~/.config/radicale/config")]
        if "RADICALE_CONFIG" in os.environ:
            config_paths.append(os.environ["RADICALE_CONFIG"])
        ignore_missing_paths = True
    try:
        configuration = config.load(config_paths,
                                    ignore_missing_paths=ignore_missing_paths)
    except Exception as e:
        print("ERROR: Invalid configuration: %s" % e, file=sys.stderr)
        if args.logging_debug:
            raise
        exit(1)

    # Update Radicale configuration according to arguments
    for group, actions in groups.items():
        section = group.title
        for action in actions:
            value = getattr(args, action)
            if value is not None:
                configuration.set(section, action.split('_', 1)[1], value)

    if args.verify_storage:
        # Write to stderr when storage verification is requested
        configuration["logging"]["config"] = ""

    # Start logging
    filename = os.path.expanduser(configuration.get("logging", "config"))
    debug = configuration.getboolean("logging", "debug")
    try:
        logger = log.start("radicale", filename, debug)
    except Exception as e:
        print("ERROR: Failed to start logger: %s" % e, file=sys.stderr)
        if debug:
            raise
        exit(1)

    if args.verify_storage:
        logger.info("Verifying storage")
        try:
            Collection = storage.load(configuration, logger)
            with Collection.acquire_lock("r"):
                if not Collection.verify():
                    logger.error("Storage verifcation failed")
                    exit(1)
        except Exception as e:
            logger.error("An exception occurred during storage verification: "
                         "%s", e, exc_info=True)
            exit(1)
        return

    try:
        serve(configuration, logger)
    except Exception as e:
        logger.error("An exception occurred during server startup: %s", e,
                     exc_info=True)
        exit(1)
Example #41
0
 def setup(self):
     self.configuration = config.load()
     self.colpath = tempfile.mkdtemp()
     self.configuration["storage"]["filesystem_folder"] = self.colpath
     # Disable syncing to disk for better performance
     self.configuration["internal"]["filesystem_fsync"] = "False"
Example #42
0
test_events = gen_events()


def get_col():
    return list(app.Collection.discover(environ['PATH_INFO'], '0'))

for type in ('multifilesystem', 'radicale_timerange_indexed_storage'):
    if len(sys.argv) > 2 and type not in sys.argv[2:]:
        continue
    shutil.rmtree(collection_folder, True)
    os.mkdir(collection_folder)
    app = Application(
        load(extra_config=dict(
            storage=dict(
                type=type,
                filesystem_folder=collection_folder
                ))),
        getLogger('rt'))

    collections = get_col()
    app.do_MKCALENDAR(environ, collections, collections, mkcal, None)

    collections = get_col()
    t0 = time()
    app.do_PUT(environ, collections, collections, test_events, None)
    print('PUT using %s %f' % (type, time() - t0))

    def f(y):
        return y['y'], y['m'], y['d'], y['h']
Example #43
0
 def setup(self):
     self.configuration = config.load()
     self.configuration.set("storage", "type", self.storage_type)
     self.logger = logging.getLogger("radicale_test")