def _init_config(): """Setup configuration dictionary from default, command line and configuration file.""" cli_opts, parser = _init_command_line_options() cli_verbose = cli_opts["verbose"] # Set config defaults config = copy.deepcopy(DEFAULT_CONFIG) # Configuration file overrides defaults config_file = cli_opts.get("config_file") if config_file: file_opts = _read_config_file(config_file, cli_verbose) util.deep_update(config, file_opts) if cli_verbose != DEFAULT_VERBOSE and "verbose" in file_opts: if cli_verbose >= 2: print( "Config file defines 'verbose: {}' but is overridden by command line: {}.".format( file_opts["verbose"], cli_verbose ) ) config["verbose"] = cli_verbose else: if cli_verbose >= 2: print("Running without configuration file.") # Command line overrides file if cli_opts.get("port"): config["port"] = cli_opts.get("port") if cli_opts.get("host"): config["host"] = cli_opts.get("host") if cli_opts.get("profile") is not None: config["profile"] = True if cli_opts.get("server") is not None: config["server"] = cli_opts.get("server") if cli_opts.get("ssl_adapter") is not None: config["ssl_adapter"] = cli_opts.get("ssl_adapter") # Command line overrides file only if -v or -q where passed: if cli_opts.get("verbose") != DEFAULT_VERBOSE: config["verbose"] = cli_opts.get("verbose") if cli_opts.get("root_path"): root_path = os.path.abspath(cli_opts.get("root_path")) config["provider_mapping"]["/"] = FilesystemProvider(root_path) if config["verbose"] >= 5: # TODO: remove passwords from user_mapping # config_cleaned = copy.deepcopy(config) print("Configuration({}):\n{}".format(cli_opts["config_file"], pformat(config))) if not config["provider_mapping"]: parser.error("No DAV provider defined.") # Quick-configuration of DomainController auth = cli_opts.get("auth") auth_conf = config.get("http_authenticator", {}) if auth and auth_conf.get("domain_controller"): parser.error( "--auth option can only be used when no domain_controller is configured" ) if auth == "anonymous": if config["simple_dc"]["user_mapping"]: parser.error( "--auth=anonymous can only be used when no user_mapping is configured" ) auth_conf.update( { "domain_controller": "wsgidav.dc.simple_dc.SimpleDomainController", "accept_basic": True, "accept_digest": True, "default_to_digest": True, } ) config["simple_dc"]["user_mapping"] = {"*": True} elif auth == "nt": if config.get("nt_dc"): parser.error( "--auth=nt can only be used when no nt_dc settings are configured" ) auth_conf.update( { "domain_controller": "wsgidav.dc.nt_dc.NTDomainController", "accept_basic": True, "accept_digest": False, "default_to_digest": False, } ) config["nt_dc"] = {} elif auth == "pam-login": if config.get("pam_dc"): parser.error( "--auth=pam-login can only be used when no pam_dc settings are configured" ) auth_conf.update( { "domain_controller": "wsgidav.dc.pam_dc.PAMDomainController", "accept_basic": True, "accept_digest": False, "default_to_digest": False, } ) config["pam_dc"] = {"service": "login"} # print(config) if cli_opts.get("reload"): print("Installing paste.reloader.", file=sys.stderr) from paste import reloader # @UnresolvedImport reloader.install() if config_file: # Add config file changes reloader.watch_file(config_file) # import pydevd # pydevd.settrace() return config
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 _init_config(): """Setup configuration dictionary from default, command line and configuration file.""" cli_opts, parser = _init_command_line_options() cli_verbose = cli_opts["verbose"] # Set config defaults config = copy.deepcopy(DEFAULT_CONFIG) # Configuration file overrides defaults config_file = cli_opts.get("config_file") if config_file: file_opts = _read_config_file(config_file, cli_verbose) util.deep_update(config, file_opts) if cli_verbose != DEFAULT_VERBOSE and "verbose" in file_opts: if cli_verbose >= 2: print( "Config file defines 'verbose: {}' but is overridden by command line: {}." .format(file_opts["verbose"], cli_verbose)) config["verbose"] = cli_verbose else: if cli_verbose >= 2: print("Running without configuration file.") # Command line overrides file if cli_opts.get("log_file"): log_file = cli_opts.get("log_file") config['log_file'] = log_file if cli_opts.get("port"): config["port"] = cli_opts.get("port") if cli_opts.get("host"): config["host"] = cli_opts.get("host") if cli_opts.get("profile") is not None: config["profile"] = True if cli_opts.get("server") is not None: config["server"] = cli_opts.get("server") if cli_opts.get("ssl_adapter") is not None: config["ssl_adapter"] = cli_opts.get("ssl_adapter") # Command line overrides file only if -v or -q where passed: if cli_opts.get("verbose") != DEFAULT_VERBOSE: config["verbose"] = cli_opts.get("verbose") if cli_opts.get("root_path"): root_path = os.path.abspath(cli_opts.get("root_path")) config["provider_mapping"]["/"] = FilesystemProvider(root_path) if config["verbose"] >= 5: # TODO: remove passwords from user_mapping # config_cleaned = copy.deepcopy(config) print("Configuration({}):\n{}".format(cli_opts["config_file"], pformat(config))) if not config["provider_mapping"]: parser.error("No DAV provider defined.") _loadSeafileSettings(config) pid_file = cli_opts.get("pidfile") if pid_file: pid_file = os.path.abspath(pid_file) config["pidfile"] = pid_file # Quick-configuration of DomainController auth = cli_opts.get("auth") auth_conf = config.get("http_authenticator", {}) if auth and auth_conf.get("domain_controller"): parser.error( "--auth option can only be used when no domain_controller is configured" ) if auth == "anonymous": if config["simple_dc"]["user_mapping"]: parser.error( "--auth=anonymous can only be used when no user_mapping is configured" ) auth_conf.update({ "domain_controller": "wsgidav.dc.simple_dc.SimpleDomainController", "accept_basic": True, "accept_digest": True, "default_to_digest": True, }) config["simple_dc"]["user_mapping"] = {"*": True} elif auth == "nt": if config.get("nt_dc"): parser.error( "--auth=nt can only be used when no nt_dc settings are configured" ) auth_conf.update({ "domain_controller": "wsgidav.dc.nt_dc.NTDomainController", "accept_basic": True, "accept_digest": False, "default_to_digest": False, }) config["nt_dc"] = {} elif auth == "pam-login": if config.get("pam_dc"): parser.error( "--auth=pam-login can only be used when no pam_dc settings are configured" ) auth_conf.update({ "domain_controller": "wsgidav.dc.pam_dc.PAMDomainController", "accept_basic": True, "accept_digest": False, "default_to_digest": False, }) config["pam_dc"] = {"service": "login"} # print(config) if cli_opts.get("reload"): print("Installing paste.reloader.", file=sys.stderr) from paste import reloader # @UnresolvedImport reloader.install() if config_file: # Add config file changes reloader.watch_file(config_file) # import pydevd # pydevd.settrace() return config
def _init_config(): """Setup configuration dictionary from default, command line and configuration file.""" cli_opts = _init_command_line_options() cli_verbose = cli_opts["verbose"] # Set config defaults # config = DEFAULT_CONFIG.copy() config = copy.deepcopy(DEFAULT_CONFIG) # Configuration file overrides defaults config_file = cli_opts.get("config_file") if config_file: file_opts = _read_config_file(config_file, cli_verbose) # config.update(file_opts) util.deep_update(config, file_opts) if cli_verbose != DEFAULT_VERBOSE and "verbose" in file_opts: if cli_verbose >= 2: print( "Config file defines 'verbose: {}' but is overridden by command line: {}." .format(file_opts["verbose"], cli_verbose)) config["verbose"] = cli_verbose else: if cli_verbose >= 2: print("Running without configuration file.") # Command line overrides file if cli_opts.get("port"): config["port"] = cli_opts.get("port") if cli_opts.get("host"): config["host"] = cli_opts.get("host") if cli_opts.get("verbose") is not None: config["verbose"] = cli_opts.get("verbose") if cli_opts.get("profile") is not None: config["profile"] = True if cli_opts.get("server") is not None: config["server"] = cli_opts.get("server") if cli_opts.get("ssl_adapter") is not None: config["ssl_adapter"] = cli_opts.get("ssl_adapter") if cli_opts.get("root_path"): root_path = os.path.abspath(cli_opts.get("root_path")) config["provider_mapping"]["/"] = FilesystemProvider(root_path) if config["verbose"] >= 5: print("Configuration({}):\n{}".format(cli_opts["config_file"], pformat(config))) if not config["provider_mapping"]: print("ERROR: No DAV provider defined. Try --help option.", file=sys.stderr) sys.exit(-1) if cli_opts.get("reload"): print("Installing paste.reloader.", file=sys.stderr) from paste import reloader # @UnresolvedImport reloader.install() if config_file: # Add config file changes reloader.watch_file(config_file) # import pydevd # pydevd.settrace() return config
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) 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>: [folder_path, is_readonly] # 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) # Figure out the domain controller, used by http_authenticator # dc = config.get("http_authenticator", {}).get("domain_controller") # if dc is True or not dc: # # True or null: # dc = SimpleDomainController # if compat.is_basestring(dc): # # If a plain string is passed, try to import it as class # dc = dynamic_import_class(dc) # if inspect.isclass(dc): # # If a class is passed, instantiate that # # assert issubclass(mw, BaseMiddleware) # TODO: remove this assert with 3.0 # dc = dc(config) # domain_controller = dc # print(domain_controller) 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 # FIXME: 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.provider_map.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())) 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: data = self.provider_map[share] hint = " (anonymous)" if data["allow_anonymous"] else "" _logger.info(" - '{}': {}{}".format(share, data["provider"], hint)) if auth_conf.get("accept_basic") and not config.get("ssl_certificate"): _logger.warn( "Basic authentication is enabled: It is highly recommended to enable SSL." ) for share, data in self.provider_map.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 = 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