def use_sentry(settings_dict: Dict) -> bool: sentry_dsn = settings_dict["SENTRY_DSN"] if not sentry_dsn: return False if not is_package_present("sentry_sdk"): settings_check_results.append( Warning("sentry_sdk must be installed.", obj="configuration")) return False # noinspection PyUnresolvedReferences import sentry_sdk # noinspection PyUnresolvedReferences from sentry_sdk.integrations.django import DjangoIntegration # noinspection PyUnresolvedReferences from sentry_sdk.integrations.celery import CeleryIntegration integrations = [DjangoIntegration()] if settings_dict["USE_CELERY"]: integrations.append(CeleryIntegration()) sentry_sdk.init( dsn=sentry_dsn, integrations=integrations, traces_sample_rate=1.0, debug=settings_dict["DEBUG"], send_default_pii=True, ) return True
def add_warning(msg, excluded_commands: Set[str] = None): if (excluded_commands and sys.argv[1:2] and sys.argv[1:2][0] in excluded_commands): return settings_check_results.append(Warning( msg, obj="configuration", ))
def from_str(value): if value not in choices: valid = ", ".join(['"%s"' % x for x in choices]) settings_check_results.append( Error( 'Invalid value "%s". Valid choices: %s.' % (value, valid), obj="configuration", )) return choices.get(value)
def process_django_ldap(self, settings_dict): if not settings_dict["AUTH_LDAP_SERVER_URI"]: return [] try: get_distribution("django-auth-ldap") except DistributionNotFound: settings_check_results.append( missing_package("django-auth-ldap", " to use LDAP authentication") ) return [] return ["django_auth_ldap.backend.LDAPBackend"]
def process_radius(self, settings_dict): if not settings_dict["RADIUS_SERVER"]: return [] try: get_distribution("django-radius") except DistributionNotFound: settings_check_results.append( missing_package("django-radius", " to use RADIUS authentication") ) return [] return ["radiusauth.backends.RADIUSBackend"]
def get_requirements(package_name, parent=None): try: yield str(package_name) d = get_distribution(package_name) for r in d.requires(): for required_package in get_requirements(r, parent=package_name): yield str(required_package) except DistributionNotFound: settings_check_results.append( missing_package(str(package_name), " by %s" % parent)) except VersionConflict: settings_check_results.append( missing_package(str(package_name), " by %s" % parent))
def get_value(self, merger, provider_name: str, setting_name: str): """ Return the value :param merger: merger object, with all interpreted settings :type merger: :class:`df_config.config.merger.SettingMerger` :param provider_name: name of the provider containing this value :param setting_name: name of the setting containing this value """ value = merger.analyze_raw_value(self.value, provider_name, setting_name) value = os.path.normpath(value) if not os.path.isfile(value): settings_check_results.append( Warning("'%s' does not exist." % value, obj="configuration")) return value
def database_engine(settings_dict): """Allow to use aliases for database engines, as well as the default dotted name""" engine = _default_database_engines.get( settings_dict["DATABASE_ENGINE"].lower(), settings_dict["DATABASE_ENGINE"] ) if engine == "django.db.backends.postgresql": try: get_distribution("psycopg2-binary") except DistributionNotFound: try: get_distribution("psycopg2") except DistributionNotFound: settings_check_results.append( missing_package("psycopg2-binary", " to use PostgreSQL database") ) elif engine == "django.db.backends.oracle": try: get_distribution("cx_Oracle") except DistributionNotFound: settings_check_results.append( missing_package("cx_Oracle", " to use Oracle database") ) elif engine == "django.db.backends.mysql": try: get_distribution("mysqlclient") except DistributionNotFound: try: get_distribution("pymysql") except DistributionNotFound: settings_check_results.append( missing_package( "mysqlclient or pymysql", " to use MySQL or MariaDB database" ) ) return engine
def process_pam(self, settings_dict): if not settings_dict["USE_PAM_AUTHENTICATION"]: return [] try: get_distribution("django_pam") except DistributionNotFound: settings_check_results.append( missing_package("django-pam", " to use PAM authentication") ) return [] # check if the current user is in the shadow group username = pwd.getpwuid(os.getuid()).pw_name if not any( x.gr_name == "shadow" and username in x.gr_mem for x in grp.getgrall() ): settings_check_results.append( Error( 'The user "%s" must belong to the "shadow" group to use PAM ' "authentication." % username, obj="configuration", ) ) return [] return ["django_pam.auth.backends.PAMBackend"]
def add_handler( self, logger: str, filename: str, level: str = "WARN", formatter=None, **kwargs ): """Add a handler to a logger. The name of the added handler is unique, so the definition of the handler is also add if required. You can use "ROOT" as logger name to target the root logger. filename: can be a filename or one of the following special values: "stderr", "stdout", "logd", "syslog" """ if filename == "stderr": handler_name = "%s.%s" % (filename, level.lower()) if formatter in ("django.server", "colorized") and not self.stderr.isatty(): formatter = None elif formatter: handler_name += ".%s" % formatter handler = { "class": "logging.StreamHandler", "level": level, "stream": "ext://sys.stderr", "formatter": formatter, } elif filename == "stdout": handler_name = "%s.%s" % (filename, level.lower()) if formatter in ("django.server", "colorized") and not self.stdout.isatty(): formatter = None elif formatter: handler_name += ".%s" % formatter handler = { "class": "logging.StreamHandler", "level": level, "stream": "ext://sys.stdout", "formatter": formatter, } elif filename == "syslog": handler_name = "%s.%s" % (filename, level.lower()) handler = {"class": "logging.handlers.SysLogHandler", "level": level} handler.update(kwargs) elif filename == "logd": try: # noinspection PyUnresolvedReferences,PyPackageRequirements import systemd.journal except ImportError: warning = Warning( "Unable to import systemd.journal (required to log with journlad)", hint=None, obj="configuration", ) settings_check_results.append(warning) # replace logd by writing to a plain-text log self.add_handler(logger, level.lower(), level=level) return handler_name = "%s.%s" % (filename, level.lower()) handler = {"class": "systemd.journal.JournalHandler", "level": level} handler.update(kwargs) else: # basename of a plain-text log log_directory = os.path.normpath(self.log_directory) if not os.path.isdir(log_directory): if not self.log_directory_warning: warning = Warning( 'Missing directory "%s"' % log_directory, hint=None, obj=log_directory, ) settings_check_results.append(warning) self.log_directory_warning = True self.add_handler(logger, "stdout", level=level, **kwargs) return basename = "%s-%s.log" % (self.log_suffix, filename) log_filename = os.path.join(log_directory, basename) try: remove = not os.path.exists(log_filename) open(log_filename, "a").close() # ok, we can write if ( remove ): # but if this file did not exist, we remove it to avoid lot of empty log files... os.remove(log_filename) except PermissionError: warning_ = Warning( 'Unable to write logs in "%s". Unsufficient rights?' % log_directory, hint=None, obj=log_directory, ) settings_check_results.append(warning_) self.add_handler(logger, "stdout", level=level, **kwargs) return handler_name = "%s.%s" % (self.log_suffix, filename) handler = { "class": "logging.handlers.RotatingFileHandler", "maxBytes": 1000000, "backupCount": 3, "formatter": "nocolor", "filename": log_filename, "level": level, "delay": True, } if not handler_name: return if handler_name not in self.handlers: self.handlers[handler_name] = handler if logger == "ROOT": target = self.root else: target = self.loggers[logger] if handler_name not in target["handlers"]: target["handlers"].append(handler_name)