예제 #1
0
    def __init__(
        self,
        app_config: CFG,
        manage_locks=True,
    ):
        super(TracimDavProvider, self).__init__()

        if manage_locks:
            self.lockManager = LockManager(LockStorage())

        self.app_config = app_config
예제 #2
0
    def __init__(self,
                 show_history=True,
                 show_deleted=True,
                 show_archived=True,
                 manage_locks=True):
        super(Provider, self).__init__()

        if manage_locks:
            self.lockManager = LockManager(LockStorage())

        self._show_archive = show_archived
        self._show_delete = show_deleted
        self._show_history = show_history
예제 #3
0
    def __init__(self, config):

        self.config = copy.deepcopy(DEFAULT_CONFIG)
        util.deep_update(self.config, config)
        # self.config.update(config)
        config = self.config

        # Evaluate configuration and set defaults
        _check_config(config)

        #        response_trailer = config.get("response_trailer", "")
        self.verbose = config.get("verbose", 3)

        lockStorage = config.get("lock_manager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            self.locksManager = None
        else:
            self.locksManager = LockManager(lockStorage)

        self.propsManager = config.get("property_manager")
        if not self.propsManager:
            # Normalize False, 0 to None
            self.propsManager = None
        elif self.propsManager is True:
            self.propsManager = PropertyManager()

        self.mount_path = config.get("mount_path")

        # Instantiate DAV resource provider objects for every share
        # provider_mapping may contain the args that are passed to a `FilesystemProvider`
        # instance:
        #     <mount_path>: <folder_path>
        # or
        #     <mount_path>: [folder_path, is_readonly]
        # or contain a complete new instance:
        #     <mount_path>: <DAVProvider Instance>

        provider_mapping = self.config["provider_mapping"]

        self.providerMap = {}
        self.sortedShareList = None
        for share, provider in provider_mapping.items():
            self.add_provider(share, provider)

        domain_controller = None

        # Define WSGI application stack
        middleware_stack = config.get("middleware_stack", [])
        mw_list = []

        # This is the 'outer' application, i.e. the WSGI application object that
        # is eventually called by the server.
        self.application = self

        # When building up the middleware stack, this app will be wrapped and replaced by the
        # next middleware in the list.
        # The `middleware_stack` is configured such that the first app in the list should be
        # called first. But since every app wraps its predecessor, we iterate in reverse
        # order:
        for mw in reversed(middleware_stack):
            # The middleware stack configuration may contain plain strings, dicts,
            # classes, or objects
            app = None
            if compat.is_basestring(mw):
                # If a plain string is passed, try to import it, assuming BaseMiddleware
                # signature
                app_class = dynamic_import_class(mw)
                app = app_class(self, self.application, config)
            elif type(mw) is dict:
                # If a dict with one entry is passed, use the key as module/class name
                # and the value as constructor arguments (positional or kwargs).
                assert len(mw) == 1
                name, args = list(mw.items())[0]
                expand = {"${application}": self.application}
                app = dynamic_instantiate_middleware(name, args, expand)
            elif inspect.isclass(mw):
                # If a class is passed, assume BaseMiddleware (or compatible)
                assert issubclass(
                    mw, BaseMiddleware
                )  # TODO: remove this assert with 3.0
                app = mw(self, self.application, config)
            else:
                # Otherwise assume an initialized middleware instance
                app = mw

            # TODO: We should try to generalize this specific code:
            if isinstance(app, HTTPAuthenticator):
                domain_controller = app.get_domain_controller()
                # Check anonymous access
                for share, data in self.providerMap.items():
                    if app.allow_anonymous_access(share):
                        data["allow_anonymous"] = True

            # Add middleware to the stack
            if app:
                mw_list.append(app)
                self.application = app
            else:
                _logger.error("Could not add middleware {}.".format(mw))

        # Print info
        _logger.info(
            "WsgiDAV/{} Python/{} {}".format(
                __version__, util.PYTHON_VERSION, platform.platform(aliased=True)
            )
        )
        if self.verbose >= 4:
            _logger.info(
                "Default encoding: {!r} (file system: {!r})".format(
                    sys.getdefaultencoding(), sys.getfilesystemencoding()
                )
            )
            _logger.info("Lock manager:      {}".format(self.locksManager))
            _logger.info("Property manager:  {}".format(self.propsManager))
            _logger.info("Domain controller: {}".format(domain_controller))

            # We traversed the stack in reverse order. Now revert again, so
            # we see the order that was configured:
            _logger.info("Middleware stack:")
            for mw in reversed(mw_list):
                _logger.info("  - {}".format(mw))

            _logger.info("Registered DAV providers by route:")
            for share in self.sortedShareList:
                data = self.providerMap[share]
                hint = " (anonymous)" if data["allow_anonymous"] else ""
                _logger.info("  - '{}': {}{}".format(share, data["provider"], hint))

        for share, data in self.providerMap.items():
            if data["allow_anonymous"]:
                # TODO: we should only warn here, if --no-auth is not given
                _logger.warn("Share '{}' will allow anonymous access.".format(share))
        return
예제 #4
0
    def __init__(self, config):
        self.config = config

        util.initLogging(config["verbose"], config.get("enable_loggers", []))

        util.log("Default encoding: %s (file system: %s)" %
                 (sys.getdefaultencoding(), sys.getfilesystemencoding()))

        # Evaluate configuration and set defaults
        _checkConfig(config)
        provider_mapping = self.config["provider_mapping"]
#        response_trailer = config.get("response_trailer", "")
        self._verbose = config.get("verbose", 2)

        lockStorage = config.get("locksmanager")
        if lockStorage is True:
            lockStorage = LockStorageDict()

        if not lockStorage:
            locksManager = None
        else:
            locksManager = LockManager(lockStorage)

        propsManager = config.get("propsmanager")
        if not propsManager:
            # Normalize False, 0 to None
            propsManager = None
        elif propsManager is True:
            propsManager = PropertyManager()

        mount_path = config.get("mount_path")

        # Instantiate DAV resource provider objects for every share
        self.providerMap = {}
        for (share, provider) in provider_mapping.items():
            # Make sure share starts with, or is, '/'
            share = "/" + share.strip("/")

            # We allow a simple string as 'provider'. In this case we interpret
            # it as a file system root folder that is published.
            if compat.is_basestring(provider):
                provider = FilesystemProvider(provider)

            assert isinstance(provider, DAVProvider)

            provider.setSharePath(share)
            if mount_path:
                provider.setMountPath(mount_path)

            # TODO: someday we may want to configure different lock/prop
            # managers per provider
            provider.setLockManager(locksManager)
            provider.setPropManager(propsManager)

            self.providerMap[share] = {
                "provider": provider, "allow_anonymous": False}

        # Define WSGI application stack
        application = RequestResolver()

        domain_controller = None
        dir_browser = config.get("dir_browser", {})
        middleware_stack = config.get("middleware_stack", [])

        # Replace WsgiDavDirBrowser to custom class for backward compatibility only
        # In normal way you should insert it into middleware_stack
        if dir_browser.get("enable", True) and "app_class" in dir_browser.keys():
            config["middleware_stack"] = [m if m != WsgiDavDirBrowser else dir_browser[
                'app_class'] for m in middleware_stack]

        for mw in middleware_stack:
            if mw.isSuitable(config):
                if self._verbose >= 2:
                    print("Middleware %s is suitable" % mw)
                application = mw(application, config)

                if issubclass(mw, HTTPAuthenticator):
                    domain_controller = application.getDomainController()
                    # check anonymous access
                    for share, data in self.providerMap.items():
                        if application.allowAnonymousAccess(share):
                            data['allow_anonymous'] = True
            else:
                if self._verbose >= 2:
                    print("Middleware %s is not suitable" % mw)

        # Print info
        if self._verbose >= 2:
            print("Using lock manager: %r" % locksManager)
            print("Using property manager: %r" % propsManager)
            print("Using domain controller: %s" % domain_controller)
            print("Registered DAV providers:")
            for share, data in self.providerMap.items():
                hint = " (anonymous)" if data['allow_anonymous'] else ""
                print("  Share '%s': %s%s" % (share, provider, hint))
        if self._verbose >= 1:
            for share, data in self.providerMap.items():
                if data['allow_anonymous']:
                    # TODO: we should only warn here, if --no-auth is not given
                    print("WARNING: share '%s' will allow anonymous access." % share)

        self._application = application
예제 #5
0
    def __init__(self, config):

        self.config = copy.deepcopy(DEFAULT_CONFIG)
        util.deep_update(self.config, config)
        config = self.config

        # Evaluate configuration and set defaults
        _check_config(config)

        self.verbose = config.get("verbose", 3)

        hotfixes = config.get("hotfixes", {})

        self.re_encode_path_info = hotfixes.get("re_encode_path_info", None)
        if self.re_encode_path_info is None:
            self.re_encode_path_info = compat.PY3

        self.unquote_path_info = hotfixes.get("unquote_path_info", False)

        lock_storage = config.get("lock_manager")
        if lock_storage is True:
            lock_storage = LockStorageDict()

        if not lock_storage:
            self.lock_manager = None
        else:
            self.lock_manager = LockManager(lock_storage)

        self.prop_manager = config.get("property_manager")
        if not self.prop_manager:
            # Normalize False, 0 to None
            self.prop_manager = None
        elif self.prop_manager is True:
            self.prop_manager = PropertyManager()

        self.mount_path = config.get("mount_path")
        auth_conf = config.get("http_authenticator", {})

        # Instantiate DAV resource provider objects for every share.
        # provider_mapping may contain the args that are passed to a
        # `FilesystemProvider` instance:
        #     <mount_path>: <folder_path>
        # or
        #     <mount_path>: { "root": <folder_path>, "readonly": True }
        # or contain a complete new instance:
        #     <mount_path>: <DAVProvider Instance>

        provider_mapping = self.config["provider_mapping"]

        self.provider_map = {}
        self.sorted_share_list = None
        for share, provider in provider_mapping.items():
            self.add_provider(share, provider)

        self.http_authenticator = None
        domain_controller = None

        # Define WSGI application stack
        middleware_stack = config.get("middleware_stack", [])
        mw_list = []

        # This is the 'outer' application, i.e. the WSGI application object that
        # is eventually called by the server.
        self.application = self

        # The `middleware_stack` is configured such that the first app in the
        # list should be called first. Since every app wraps its predecessor, we
        # iterate in reverse order:
        for mw in reversed(middleware_stack):
            # The middleware stack configuration may contain plain strings, dicts,
            # classes, or objects
            app = None
            if compat.is_basestring(mw):
                # If a plain string is passed, try to import it, assuming
                # `BaseMiddleware` signature
                app_class = dynamic_import_class(mw)
                app = app_class(self, self.application, config)
            elif type(mw) is dict:
                # If a dict with one entry is passed, use the key as module/class name
                # and the value as constructor arguments (positional or kwargs).
                assert len(mw) == 1
                name, args = list(mw.items())[0]
                expand = {"${application}": self.application}
                app = dynamic_instantiate_middleware(name, args, expand)
            elif inspect.isclass(mw):
                # If a class is passed, assume BaseMiddleware (or compatible)
                assert issubclass(
                    mw, BaseMiddleware)  # TODO: remove this assert with 3.0
                app = mw(self, self.application, config)
            else:
                # Otherwise assume an initialized middleware instance
                app = mw

            # Remember
            if isinstance(app, HTTPAuthenticator):
                self.http_authenticator = app
                domain_controller = app.get_domain_controller()

            # Add middleware to the stack
            if app:
                if callable(getattr(app, "is_disabled",
                                    None)) and app.is_disabled():
                    _logger.warning(
                        "App {}.is_disabled() returned True: skipping.".format(
                            app))
                else:
                    mw_list.append(app)
                    self.application = app
            else:
                _logger.error("Could not add middleware {}.".format(mw))

        domain_controller
        # Print info
        _logger.info("WsgiDAV/{} Python/{} {}".format(
            __version__, util.PYTHON_VERSION, platform.platform(aliased=True)))
        if self.verbose >= 4:
            _logger.info("Default encoding: {!r} (file system: {!r})".format(
                sys.getdefaultencoding(), sys.getfilesystemencoding()))

        if self.verbose >= 3:
            _logger.info("Lock manager:      {}".format(self.lock_manager))
            _logger.info("Property manager:  {}".format(self.prop_manager))
            _logger.info("Domain controller: {}".format(domain_controller))

        if self.verbose >= 4:
            # We traversed the stack in reverse order. Now revert again, so
            # we see the order that was configured:
            _logger.info("Middleware stack:")
            for mw in reversed(mw_list):
                _logger.info("  - {}".format(mw))

        if self.verbose >= 3:
            _logger.info("Registered DAV providers by route:")
            for share in self.sorted_share_list:
                provider = self.provider_map[share]
                hint = (" (anonymous)"
                        if domain_controller.is_share_anonymous(share) else "")
                _logger.info("  - '{}': {}{}".format(share, provider, hint))

        if auth_conf.get("accept_basic") and not config.get("ssl_certificate"):
            _logger.warning(
                "Basic authentication is enabled: It is highly recommended to enable SSL."
            )

        if domain_controller:
            for share, provider in self.provider_map.items():
                if domain_controller.is_share_anonymous(share):
                    _logger.warning(
                        "Share '{}' will allow anonymous {} access.".format(
                            share,
                            "read" if provider.is_readonly() else "write"))
        return
예제 #6
0
def test():
    logging.info("test.test()")

    logging.getLogger().setLevel(logging.DEBUG)

    # Test data_fs.py
    data_fs.initfs()
    assert data_fs.isdir("/")

    rootpath = "/run_test"
    if data_fs.exists(rootpath):
        logging.info("removing " + rootpath)
        data_fs.rmtree(rootpath)
    assert not data_fs.exists(rootpath)

    data_fs.mkdir(rootpath)
    assert data_fs.isdir(rootpath)

    data = b"file content"
    data_fs.mkdir(rootpath + "/dir1")
    assert data_fs.isdir(rootpath + "/dir1")
    f1 = data_fs.btopen(rootpath + "/dir1/file1.txt", "w")
    f1.write(data)
    f1.close()
    assert data_fs.isfile(rootpath + "/dir1/file1.txt")

    # data_fs.unlink(rootpath+"/dir1/file1.txt")
    # assert not data_fs.isfile(rootpath+"/dir1/file1.txt")

    print("*** data_fs tests passed ***")

    # Test providers
    provider = BTFSResourceProvider()
    lockman = LockManager(LockStorageMemcache())
    provider.set_lock_manager(lockman)
    environ = {"wsgidav.provider": provider}
    environ["wsgidav.auth.user_name"] = "test"
    environ["wsgidav.auth.roles"] = ["editor"]

    resRoot = provider.get_resource_inst(rootpath + "/", environ)
    resRoot.create_collection("folder1")
    assert data_fs.isdir(rootpath + "/folder1")
    assert not data_fs.isfile(rootpath + "/folder1")
    resChild = provider.get_resource_inst(rootpath + "/folder1", environ)
    assert resChild
    resFile = resChild.create_empty_resource("file_empty.txt")
    assert resFile
    assert not data_fs.isdir(rootpath + "/folder1/file_empty.txt")
    assert data_fs.isfile(rootpath + "/folder1/file_empty.txt")
    # write
    data = b"x" * 1024
    res = resChild.create_empty_resource("file2.txt")
    f = res.begin_write()
    f.write(data)
    f.close()
    # copy
    res = provider.get_resource_inst(rootpath + "/folder1/file2.txt", environ)
    res.copy_move_single(rootpath + "/folder1/file2_copy.txt", False)

    res = provider.get_resource_inst(rootpath + "/folder1/file2_copy.txt",
                                     environ)
    f = res.get_content()
    assert data == f.read()
    f.close()

    print("*** provider tests passed ***")

    lock = provider.lock_manager.acquire(
        rootpath + "/folder1",
        "write",
        "exclusive",
        "infinity",
        b"test_owner",
        timeout=100,
        principal="martin",
        token_list=[],
    )
    assert lock["root"] == rootpath + "/folder1"
    lock = provider.lock_manager.get_lock(lock["token"])
    print(lock_string(lock))
    assert lock["root"] == rootpath + "/folder1"

    locklist = provider.lock_manager.get_indirect_url_lock_list(
        rootpath + "/folder1/file2.txt")
    print(locklist)
    assert len(locklist) == 1

    print("*** lock tests passed ***")