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
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
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
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
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
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 ***")