Ejemplo n.º 1
0
from django.core.checks import register, Error, Warning, Info
from django.core import mail
from django.conf import settings

E001 = Error('EMAIL_BACKEND is set to a testing/debug backend.',
             id='preflight_email.E001')

E002 = Error("DEFAULT_FROM_EMAIL is set to an @localhost address.",
             id='preflight_email.E002')

W001 = Warning('Can not send email, check your email settings.',
               id='preflight_email.W001')

I001 = Info("SERVER_EMAIL is still set to 'root@localhost'.",
            id='preflight_email.I001')


# noinspection PyUnusedLocal
@register('preflight', deploy=True)
def check_email(app_configs, **kwargs):
    errors = []

    # Check for debug-ish email backends
    if settings.EMAIL_BACKEND in [
            'django.core.mail.backends.console.EmailBackend',
            'django.core.mail.backends.filebased.EmailBackend',
            'django.core.mail.backends.locmem.EmailBackend',
    ]:
        errors.append(E001)

    # So we assume if you set the dummy backend, you are not interested in mail,
Ejemplo n.º 2
0
from django.conf import settings
from django.core.checks import Warning, register
from django.utils.translation import ugettext as _

W001 = Warning(
    _("You have USE_TZ set to False, this may result in issues during "
      "transitions between summer/winter time (ie the same local time occuring "
      "twice due to clock change)."),
    hint=_("Set `USE_TZ = True` in settings.py"),
    id="modoboa.W001",
)


@register(deploy=True)
def check_use_tz_enabled(app_configs, **kwargs):
    """Ensure USE_TZ is enabled in settings.py

    When USE_TZ is enabled all date/times are stored in UTC.
    Fixes #1086 - https://github.com/modoboa/modoboa/issues/1086
    """
    errors = []
    if not settings.USE_TZ:
        errors.append(W001)
    return errors
Ejemplo n.º 3
0
def best_practice(app_configs, **kwargs):
    """
    Test for configuration recommendations. These are best practices, they
    avoid hard to find bugs and unexpected behaviour.
    """
    if app_configs is None:
        app_configs = apps.get_app_configs()

    # Django 2.0 support
    INSTALLED_APPS = settings.INSTALLED_APPS

    if not hasattr(settings, 'TENANT_APPS'):
        return [Critical('TENANT_APPS setting not set')]

    if not hasattr(settings, 'TENANT_MODEL'):
        return [Critical('TENANT_MODEL setting not set')]

    if not hasattr(settings, 'SHARED_APPS'):
        return [Critical('SHARED_APPS setting not set')]

    if 'tenant_schemas.routers.TenantSyncRouter' not in settings.DATABASE_ROUTERS:
        return [
            Critical("DATABASE_ROUTERS setting must contain "
                     "'tenant_schemas.routers.TenantSyncRouter'.")
        ]

    errors = []

    django_index = next(i for i, s in enumerate(INSTALLED_APPS)
                        if s.startswith('django.'))
    if INSTALLED_APPS.index('tenant_schemas') > django_index:
        errors.append(
            Warning(
                "You should put 'tenant_schemas' before any django "
                "core applications in INSTALLED_APPS.",
                obj="django.conf.settings",
                hint="This is necessary to overwrite built-in django "
                "management commands with their schema-aware "
                "implementations.",
                id="tenant_schemas.W001"))

    if not settings.TENANT_APPS:
        errors.append(
            Error("TENANT_APPS is empty.",
                  hint="Maybe you don't need this app?",
                  id="tenant_schemas.E001"))

    if hasattr(settings, 'PG_EXTRA_SEARCH_PATHS'):
        if get_public_schema_name() in settings.PG_EXTRA_SEARCH_PATHS:
            errors.append(
                Critical("%s can not be included on PG_EXTRA_SEARCH_PATHS." %
                         get_public_schema_name()))

        # make sure no tenant schema is in settings.PG_EXTRA_SEARCH_PATHS
        invalid_schemas = set(settings.PG_EXTRA_SEARCH_PATHS).intersection(
            get_tenant_model().objects.all().values_list('schema_name',
                                                         flat=True))
        if invalid_schemas:
            errors.append(
                Critical(
                    "Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS."
                    % ", ".join(sorted(invalid_schemas))))

    if not settings.SHARED_APPS:
        errors.append(
            Warning("SHARED_APPS is empty.", id="tenant_schemas.W002"))

    if not set(settings.TENANT_APPS).issubset(INSTALLED_APPS):
        delta = set(settings.TENANT_APPS).difference(INSTALLED_APPS)
        errors.append(
            Error("You have TENANT_APPS that are not in INSTALLED_APPS",
                  hint=[a for a in settings.TENANT_APPS if a in delta],
                  id="tenant_schemas.E002"))

    if not set(settings.SHARED_APPS).issubset(INSTALLED_APPS):
        delta = set(settings.SHARED_APPS).difference(INSTALLED_APPS)
        errors.append(
            Error("You have SHARED_APPS that are not in INSTALLED_APPS",
                  hint=[a for a in settings.SHARED_APPS if a in delta],
                  id="tenant_schemas.E003"))

    if not isinstance(default_storage, TenantStorageMixin):
        errors.append(
            Warning("Your default storage engine is not tenant aware.",
                    hint="Set settings.DEFAULT_FILE_STORAGE to "
                    "'tenant_schemas.storage.TenantFileSystemStorage'",
                    id="tenant_schemas.W003"))

    return errors
Ejemplo n.º 4
0
    def check_email_appellation_priority_list(self):
        errors = []
        self._email_appellation_priority_list = (
            DEFAULT_EMAIL_APPELLATION_PRIORITY_LIST)

        from django.conf import settings
        custom_email_appellation_priority_list = getattr(
            settings, RELATE_EMAIL_APPELLATION_PRIORITY_LIST, None)
        if not custom_email_appellation_priority_list:
            if hasattr(settings, "RELATE_EMAIL_APPELATION_PRIORITY_LIST"):
                if settings.RELATE_EMAIL_APPELATION_PRIORITY_LIST is not None:
                    errors.append(
                        Warning(
                            msg=("'RELATE_EMAIL_APPELATION_PRIORITY_LIST' is "
                                 "deprecated due to typo, use "
                                 "'RELATE_EMAIL_APPELLATION_PRIORITY_LIST' "
                                 "instead."),
                            id="relate_email_appellation_priority_list.W003"))
                    custom_email_appellation_priority_list = (
                        settings.RELATE_EMAIL_APPELATION_PRIORITY_LIST)
        if not custom_email_appellation_priority_list:
            return errors

        if not isinstance(custom_email_appellation_priority_list,
                          (list, tuple)):
            errors.append(
                Warning(msg=(
                    "%s, %s" %
                    (INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_EMAIL_APPELLATION_PRIORITY_LIST,
                        "types": "list or tuple"
                    }, "default value '%s' will be used" %
                     repr(DEFAULT_EMAIL_APPELLATION_PRIORITY_LIST))),
                        id="relate_email_appellation_priority_list.W001"))
            return errors

        priority_list = []
        not_supported_appels = []

        # filter out not allowd appellations in customized list
        for appell in custom_email_appellation_priority_list:
            if appell in DEFAULT_EMAIL_APPELLATION_PRIORITY_LIST:
                priority_list.append(appell)
            else:
                not_supported_appels.append(appell)

        # make sure the default appellations are included in case
        # user defined appellations are not available.
        for appell in DEFAULT_EMAIL_APPELLATION_PRIORITY_LIST:
            if appell not in priority_list:
                priority_list.append(appell)

        assert len(priority_list)
        self._email_appellation_priority_list = priority_list

        if not_supported_appels:
            errors.append(
                Warning(msg=(
                    "%(location)s: not supported email appelation(s) found "
                    "and will be ignored: %(not_supported_appelds)s. "
                    "%(actual)s will be used as "
                    "relate_email_appellation_priority_list." % {
                        "location": RELATE_EMAIL_APPELLATION_PRIORITY_LIST,
                        "not_supported_appelds":
                        ", ".join(not_supported_appels),
                        "actual": repr(priority_list)
                    }),
                        id="relate_email_appellation_priority_list.W002"))
        return errors
Ejemplo n.º 5
0
 def test_shared_apps_empty(self):
     self.assertBestPractice([
         Warning("SHARED_APPS is empty.",
                 id="wagtailtenant.W002"),
     ])
Ejemplo n.º 6
0
import re

from django.core.checks import Tags, Warning, register

from dbbackup import settings

W001 = Warning('Invalid HOSTNAME parameter',
               hint='Set a non empty string to this settings.DBBACKUP_HOSTNAME',
               id='dbbackup.W001')
W002 = Warning('Invalid STORAGE parameter',
               hint='Set a valid path to a storage in settings.DBBACKUP_STORAGE',
               id='dbbackup.W002')
W003 = Warning('Invalid FILENAME_TEMPLATE parameter',
               hint='Include {datetime} to settings.DBBACKUP_FILENAME_TEMPLATE',
               id='dbbackup.W003')
W004 = Warning('Invalid MEDIA_FILENAME_TEMPLATE parameter',
               hint='Include {datetime} to settings.DBBACKUP_MEDIA_FILENAME_TEMPLATE',
               id='dbbackup.W004')
W005 = Warning('Invalid DATE_FORMAT parameter',
               hint='settings.DBBACKUP_DATE_FORMAT can contain only [A-Za-z0-9%_-]',
               id='dbbackup.W005')
W006 = Warning('FAILURE_RECIPIENTS has been deprecated',
               hint='settings.DBBACKUP_FAILURE_RECIPIENTS is replaced by '
                    'settings.DBBACKUP_ADMINS',
               id='dbbackup.W006')


@register(Tags.compatibility)
def check_settings(app_configs, **kwargs):
    errors = []
    if not settings.HOSTNAME:
Ejemplo n.º 7
0
        "AUTH_USER_MODEL to django-miniuser's MiniUser-class."),
    id='miniuser.e011',
)

I001 = Info(
    _("It seems, that you have not activated Django's admin backend."),
    hint=_(
        "If you are running without Django's admin backend, several features of "
        "django-miniuser will not be available."),
    id='miniuser.i001',
)

W001 = Warning(
    _("LOGIN_URL is not 'miniuser:login'."),
    hint=_(
        "If you want to use MiniUsers login-functions, add LOGIN_URL to your "
        "settings or modify its setting to 'miniuser:login'."),
    id='miniuser.w001',
)


def check_correct_values(app_configs, **kwargs):
    """Checks, if all app specific settings have defined values"""

    errors = []

    if not isinstance(settings.MINIUSER_DEFAULT_ACTIVE, bool):
        errors.append(E001)
    if settings.MINIUSER_LOGIN_NAME not in ('username', 'email', 'both'):
        errors.append(E002)
    if not isinstance(settings.MINIUSER_REQUIRE_VALID_EMAIL, bool):
Ejemplo n.º 8
0
import logging

import requests
from django.conf import settings
from django.core.checks import Warning, register
from social_core.backends.google import GoogleOAuth2
from social_core.backends.linkedin import LinkedinOAuth2

logger = logging.getLogger(__name__)

W001 = Warning(
    "Incorrect Twitter auth credentials. Ensure that the SOCIAL_AUTH_TWITTER_* settings are correctly configured.",
    id='forsta_auth.W001',
)

W002 = Warning(
    "Incorrect Google auth credentials. Ensure that the SOCIAL_AUTH_GOOGLE_OAUTH2_* settings are correctly configured.",
    id='forsta_auth.W002',
)

W003 = Warning(
    "Incorrect LinkedIn auth credentials. Ensure that the SOCIAL_AUTH_LINKEDIN_OAUTH2_* settings are correctly "
    "configured.",
    id='forsta_auth.W003',
)


@register('integration', deploy=True)
def check_twitter_credentials(app_configs, **kwargs):
    if getattr(settings, 'SOCIAL_AUTH_TWITTER_KEY', None) is not None:
        response = requests.post('https://api.twitter.com/oauth2/token',
Ejemplo n.º 9
0
import pwd
import os

from django.core.checks import register, Warning
from django.conf import settings

#
# Internal checks
#

W001 = Warning(
    'No DEPLOY_TARGET_USER set, define it to check write permissions on storages.',
    id='preflight.W001')

W002 = Warning(
    'You are not running as DEPLOY_TARGET_USER, writeable-checks can not be trusted.',
    id='preflight.W002')


# noinspection PyUnusedLocal
@register('preflight', deploy=True)
def check_user(app_configs, **kwargs):
    errors = []

    current_user = pwd.getpwuid(os.getuid()).pw_name
    target_user = getattr(settings, 'DEPLOY_TARGET_USER', None)

    if target_user is None:
        errors.append(W001)

    if target_user and target_user != current_user:
Ejemplo n.º 10
0
# -*- coding: utf-8 -*-

from __future__ import unicode_literals

from django.conf import settings
from django.core.checks import Warning, register
from django.db import connections
from django.utils.translation import ugettext as _

W001 = Warning(
    _("AMAVIS_DEFAULT_DATABASE_ENCODING does not match the character "
      "encoding used by the Amavis database."),
    hint=_("Check your database character encoding and set/update "
           "AMAVIS_DEFAULT_DATABASE_ENCODING."),
    id="modoboa-amavis.W001",
)

W002 = Warning(
    _("Modoboa Amavis has not been tested using the selected database engine."
      ),
    hint=_("Try using PostgreSQL, MySQL or MariaDB."),
    id="modoboa-amavis.W002",
)


@register(deploy=True)
def check_amavis_database_encoding(app_configs, **kwargs):
    """Ensure AMAVIS_DEFAULT_DATABASE_ENCODING is set to the correct value."""
    errors = []
    db_engine = settings.DATABASES["amavis"]["ENGINE"]
    sql_query = None
Ejemplo n.º 11
0
    def test_database_compatibility(self):
        compatible_database = {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': 'non_existent_db.sqlite3',
        }
        incompatible_database = {
            'ENGINE': 'django.db.backends.oracle',
            'NAME': 'non_existent_db',
        }

        warning002 = Warning(
            'None of the configured databases are supported '
            'by django-cachalot.',
            hint='Use a supported database, or remove django-cachalot, or '
            'put at least one database alias in `CACHALOT_DATABASES` '
            'to force django-cachalot to use it.',
            id='cachalot.W002')
        warning003 = Warning(
            'Database engine %r is not supported by django-cachalot.' %
            'django.db.backends.oracle',
            hint='Switch to a supported database engine.',
            id='cachalot.W003')
        warning004 = Warning(
            'Django-cachalot is useless because no database '
            'is configured in `CACHALOT_DATABASES`.',
            hint='Reconfigure django-cachalot or remove it.',
            id='cachalot.W004')
        error001 = Error(
            'Database alias %r from `CACHALOT_DATABASES` '
            'is not defined in `DATABASES`.' % 'secondary',
            hint='Change `CACHALOT_DATABASES` to be compliant with'
            '`CACHALOT_DATABASES`',
            id='cachalot.E001',
        )
        error002 = Error(
            "`CACHALOT_DATABASES` must be either %r or a list, tuple, "
            "frozenset or set of database aliases." % SUPPORTED_ONLY,
            hint='Remove `CACHALOT_DATABASES` or change it.',
            id='cachalot.E002',
        )

        with self.settings(DATABASES={'default': incompatible_database}):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [warning002])

        with self.settings(DATABASES={
                'default': compatible_database,
                'secondary': incompatible_database
        }):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [])
        with self.settings(DATABASES={
                'default': incompatible_database,
                'secondary': compatible_database
        }):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [])

        with self.settings(DATABASES={'default': incompatible_database},
                           CACHALOT_DATABASES=['default']):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [warning003])

        with self.settings(DATABASES={'default': incompatible_database},
                           CACHALOT_DATABASES=[]):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [warning004])

        with self.settings(DATABASES={'default': incompatible_database},
                           CACHALOT_DATABASES=['secondary']):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [error001])
        with self.settings(DATABASES={'default': compatible_database},
                           CACHALOT_DATABASES=['default', 'secondary']):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [error001])

        with self.settings(CACHALOT_DATABASES='invalid value'):
            errors = run_checks(tags=[Tags.compatibility])
            self.assertListEqual(errors, [error002])
Ejemplo n.º 12
0
import smtplib

from django.core import mail
from django.core.checks import Tags, Warning, register
from django.core.mail.backends.smtp import EmailBackend

W001 = Warning(
    "Unable to connect to an SMTP server. Ensure that the EMAIL_* settings are correctly configured.",
    id='onboarding.W001',
)


@register('integration', deploy=True)
def check_email_config(app_configs, **kwargs):
    """Ensures we can connect to an email server

    Doesn't check whether authentication would be required if none is configured, but will check credentials if they
    are provided. This will therefore catch expired or no-longer-valid credentials."""
    connection = mail.get_connection()
    if isinstance(connection, EmailBackend):
        try:
            connection.open()
        except smtplib.SMTPAuthenticationError:
            return [W001]
    return []
Ejemplo n.º 13
0
def check_middleware(app_configs, **kwargs):
    from debug_toolbar.middleware import DebugToolbarMiddleware

    errors = []
    gzip_index = None
    debug_toolbar_indexes = []

    if all(not check_template_config(config) for config in settings.TEMPLATES):
        errors.append(
            Warning(
                "At least one DjangoTemplates TEMPLATES configuration needs "
                "to use django.template.loaders.app_directories.Loader or "
                "have APP_DIRS set to True.",
                hint=("Include django.template.loaders.app_directories.Loader "
                      'in ["OPTIONS"]["loaders"]. Alternatively use '
                      "APP_DIRS=True for at least one "
                      "django.template.backends.django.DjangoTemplates "
                      "backend configuration."),
                id="debug_toolbar.W006",
            ))

    # If old style MIDDLEWARE_CLASSES is being used, report an error.
    if settings.is_overridden("MIDDLEWARE_CLASSES"):
        errors.append(
            Warning(
                "debug_toolbar is incompatible with MIDDLEWARE_CLASSES setting.",
                hint="Use MIDDLEWARE instead of MIDDLEWARE_CLASSES",
                id="debug_toolbar.W004",
            ))
        return errors

    # Determine the indexes which gzip and/or the toolbar are installed at
    for i, middleware in enumerate(settings.MIDDLEWARE):
        if is_middleware_class(GZipMiddleware, middleware):
            gzip_index = i
        elif is_middleware_class(DebugToolbarMiddleware, middleware):
            debug_toolbar_indexes.append(i)

    if not debug_toolbar_indexes:
        # If the toolbar does not appear, report an error.
        errors.append(
            Warning(
                "debug_toolbar.middleware.DebugToolbarMiddleware is missing "
                "from MIDDLEWARE.",
                hint="Add debug_toolbar.middleware.DebugToolbarMiddleware to "
                "MIDDLEWARE.",
                id="debug_toolbar.W001",
            ))
    elif len(debug_toolbar_indexes) != 1:
        # If the toolbar appears multiple times, report an error.
        errors.append(
            Warning(
                "debug_toolbar.middleware.DebugToolbarMiddleware occurs "
                "multiple times in MIDDLEWARE.",
                hint="Load debug_toolbar.middleware.DebugToolbarMiddleware only "
                "once in MIDDLEWARE.",
                id="debug_toolbar.W002",
            ))
    elif gzip_index is not None and debug_toolbar_indexes[0] < gzip_index:
        # If the toolbar appears before the gzip index, report an error.
        errors.append(
            Warning(
                "debug_toolbar.middleware.DebugToolbarMiddleware occurs before "
                "django.middleware.gzip.GZipMiddleware in MIDDLEWARE.",
                hint="Move debug_toolbar.middleware.DebugToolbarMiddleware to "
                "after django.middleware.gzip.GZipMiddleware in MIDDLEWARE.",
                id="debug_toolbar.W003",
            ))
    return errors
Ejemplo n.º 14
0
 def test_shared_apps_empty(self):
     self.assertBestPractice([
         Warning("SHARED_APPS is empty."),
     ])
Ejemplo n.º 15
0
 def setUp(self):
     self.disable_success_access_log_warning = Warning(
         msg=Messages.SETTING_DEPRECATED.format(deprecated_setting='AXES_DISABLE_SUCCESS_ACCESS_LOG'),
         hint=Hints.SETTING_DEPRECATED,
         id=Codes.SETTING_DEPRECATED,
     )
Ejemplo n.º 16
0
def microsoft_auth_validator(app_configs, **kwargs):
    from django.contrib.sites.models import Site

    from .conf import HOOK_SETTINGS, config

    errors = []

    if apps.is_installed("microsoft_auth"
                         ) and not apps.is_installed("django.contrib.sites"):

        errors.append(
            Critical(
                "`django.contrib.sites` is not installed",
                hint=("`microsoft_auth` requires `django.contrib.sites` "
                      "to be installed and configured"),
                id="microsoft_auth.E001",
            ))

    try:
        if not hasattr(config, "SITE_ID"):
            request = RequestFactory().get("/", HTTP_HOST="example.com")
            current_site = Site.objects.get_current(request)
        else:
            current_site = Site.objects.get_current()
    except Site.DoesNotExist:
        pass
    except (OperationalError, ProgrammingError):
        errors.append(
            Warning(
                "`django.contrib.sites` migrations not ran",
                id="microsoft_auth.W001",
            ))
    else:
        if current_site.domain == "example.com":
            errors.append(
                Warning(
                    ("`example.com` is still a valid site, Microsoft "
                     "auth might not work"),
                    hint=("Microsoft/Xbox auth uses OAuth, which requires "
                          "a real redirect URI to come back to"),
                    id="microsoft_auth.W002",
                ))

    if config.MICROSOFT_AUTH_LOGIN_ENABLED:  # pragma: no branch
        if config.MICROSOFT_AUTH_CLIENT_ID == "":
            errors.append(
                Warning(
                    ("`MICROSOFT_AUTH_CLIENT_ID` is not configured"),
                    hint=("`MICROSOFT_AUTH_LOGIN_ENABLED` is `True`, but "
                          "`MICROSOFT_AUTH_CLIENT_ID` is empty. Microsoft "
                          "auth will be disabled"),
                    id="microsoft_auth.W003",
                ))
        if config.MICROSOFT_AUTH_CLIENT_SECRET == "":
            errors.append(
                Warning(
                    ("`MICROSOFT_AUTH_CLIENT_SECRET` is not configured"),
                    hint=("`MICROSOFT_AUTH_LOGIN_ENABLED` is `True`, but "
                          "`MICROSOFT_AUTH_CLIENT_SECRET` is empty. Microsoft "
                          "auth will be disabled"),
                    id="microsoft_auth.W004",
                ))

    for hook_setting_name in HOOK_SETTINGS:
        hook_setting = getattr(config, hook_setting_name)
        if hook_setting != "":
            parts = hook_setting.rsplit(".", 1)

            if len(parts) != 2:
                errors.append(
                    Critical(
                        ("{} is not a valid python path".format(hook_setting)),
                        id="microsoft_auth.E002",
                    ))
                return errors

            module_path, function_name = parts[0], parts[1]
            try:
                module = importlib.import_module(module_path)
            except ImportError:
                errors.append(
                    Critical(
                        ("{} is not a valid module".format(module_path)),
                        id="microsoft_auth.E003",
                    ))
                return errors

            try:
                function = getattr(module, function_name)
            except AttributeError:
                errors.append(
                    Critical(
                        ("{} does not exist".format(hook_setting)),
                        id="microsoft_auth.E004",
                    ))
                return errors

            if not callable(function):
                errors.append(
                    Critical(
                        ("{} is not a callable".format(hook_setting)),
                        id="microsoft_auth.E005",
                    ))

    return errors
Ejemplo n.º 17
0
 def add_warning(self, title, numeric_id: int, **kwargs):
     kwargs.setdefault('obj', self.app_config.label)
     issue_id = 'otree.W' + str(numeric_id).zfill(3)
     return self.errors.append(Warning(title, id=issue_id, **kwargs))
Ejemplo n.º 18
0
def check_relate_settings(app_configs, **kwargs):
    errors = []

    # {{{ check RELATE_BASE_URL
    relate_base_url = getattr(settings, RELATE_BASE_URL, None)
    if relate_base_url is None:
        errors.append(
            RelateCriticalCheckMessage(msg=REQUIRED_CONF_ERROR_PATTERN %
                                       {"location": RELATE_BASE_URL},
                                       id="relate_base_url.E001"))
    elif not isinstance(relate_base_url, str):
        errors.append(
            RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                "location": RELATE_BASE_URL,
                "types": "str"
            }),
                                       id="relate_base_url.E002"))
    elif not relate_base_url.strip():
        errors.append(
            RelateCriticalCheckMessage(
                msg="%(location)s should not be an empty string" %
                {"location": RELATE_BASE_URL},
                id="relate_base_url.E003"))
    # }}}

    from accounts.utils import relate_user_method_settings
    # check RELATE_EMAIL_APPELLATION_PRIORITY_LIST
    errors.extend(
        relate_user_method_settings.check_email_appellation_priority_list())

    # check RELATE_CSV_SETTINGS
    errors.extend(relate_user_method_settings.check_custom_full_name_method())

    # check RELATE_USER_PROFILE_MASK_METHOD
    errors.extend(relate_user_method_settings.check_user_profile_mask_method())

    # {{{ check EMAIL_CONNECTIONS
    email_connections = getattr(settings, EMAIL_CONNECTIONS, None)
    if email_connections is not None:
        if not isinstance(email_connections, dict):
            errors.append(
                RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                    "location": EMAIL_CONNECTIONS,
                    "types": "dict"
                }),
                                           id="email_connections.E001"))
        else:
            for label, c in six.iteritems(email_connections):
                if not isinstance(c, dict):
                    errors.append(
                        RelateCriticalCheckMessage(
                            msg=(INSTANCE_ERROR_PATTERN % {
                                "location":
                                "'%s' in '%s'" % (label, EMAIL_CONNECTIONS),
                                "types":
                                "dict"
                            }),
                            id="email_connections.E002"))
                else:
                    if "backend" in c:
                        try:
                            import_string(c["backend"])
                        except ImportError as e:
                            errors.append(
                                RelateCriticalCheckMessage(
                                    msg=(GENERIC_ERROR_PATTERN % {
                                        "location":
                                        "'%s' in %s" %
                                        (label, RELATE_FACILITIES),
                                        "error_type":
                                        type(e).__name__,
                                        "error_str":
                                        str(e)
                                    }),
                                    id="email_connections.E003"))
    # }}}

    # {{{ check RELATE_FACILITIES

    relate_facilities_conf = getattr(settings, RELATE_FACILITIES, None)
    if relate_facilities_conf is not None:
        from course.utils import get_facilities_config
        try:
            facilities = get_facilities_config()
        except Exception as e:
            errors.append(
                RelateCriticalCheckMessage(msg=(GENERIC_ERROR_PATTERN % {
                    "location": RELATE_FACILITIES,
                    "error_type": type(e).__name__,
                    "error_str": str(e)
                }),
                                           id="relate_facilities.E001"))
        else:
            if not isinstance(facilities, dict):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "'%(location)s' must either be or return a dictionary"
                        % {
                            "location": RELATE_FACILITIES
                        }),
                                               id="relate_facilities.E002"))
            else:
                for facility, conf in six.iteritems(facilities):
                    if not isinstance(conf, dict):
                        errors.append(
                            RelateCriticalCheckMessage(
                                msg=(INSTANCE_ERROR_PATTERN % {
                                    "location":
                                    "Facility `%s` in %s" %
                                    (facility, RELATE_FACILITIES),
                                    "types":
                                    "dict"
                                }),
                                id="relate_facilities.E003"))
                    else:
                        ip_ranges = conf.get("ip_ranges", [])
                        if ip_ranges:
                            if not isinstance(ip_ranges, (list, tuple)):
                                errors.append(
                                    RelateCriticalCheckMessage(
                                        msg=(INSTANCE_ERROR_PATTERN % {
                                            "location":
                                            "'ip_ranges' in facility `%s` in %s"
                                            % (facilities, RELATE_FACILITIES),
                                            "types":
                                            "list or tuple"
                                        }),
                                        id="relate_facilities.E004"))
                            else:
                                for ip_range in ip_ranges:
                                    try:
                                        get_ip_network(ip_range)
                                    except Exception as e:
                                        errors.append(
                                            RelateCriticalCheckMessage(
                                                msg=(GENERIC_ERROR_PATTERN % {
                                                    "location":
                                                    "'ip_ranges' in "
                                                    "facility `%s` in %s" %
                                                    (facility,
                                                     RELATE_FACILITIES),
                                                    "error_type":
                                                    type(e).__name__,
                                                    "error_str":
                                                    str(e)
                                                }),
                                                id="relate_facilities.E005"))
                        else:
                            if not callable(relate_facilities_conf):
                                errors.append(
                                    Warning(msg=(
                                        "Faclity `%s` in %s is an open facility "
                                        "as it has no configured `ip_ranges`" %
                                        (facility, RELATE_FACILITIES)),
                                            id="relate_facilities.W001"))

    # }}}

    # {{{ check RELATE_MAINTENANCE_MODE_EXCEPTIONS
    relate_maintenance_mode_exceptions = getattr(
        settings, RELATE_MAINTENANCE_MODE_EXCEPTIONS, None)
    if relate_maintenance_mode_exceptions is not None:
        if not isinstance(relate_maintenance_mode_exceptions, (list, tuple)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_MAINTENANCE_MODE_EXCEPTIONS,
                        "types": "list or tuple"
                    }),
                    id="relate_maintenance_mode_exceptions.E001"))
        else:
            for ip in relate_maintenance_mode_exceptions:
                try:
                    get_ip_network(ip)
                except Exception as e:
                    errors.append(
                        RelateCriticalCheckMessage(
                            msg=(GENERIC_ERROR_PATTERN % {
                                "location":
                                "ip/ip_ranges '%s' in %s" %
                                (ip, RELATE_FACILITIES),
                                "error_type":
                                type(e).__name__,
                                "error_str":
                                str(e)
                            }),
                            id="relate_maintenance_mode_exceptions.E002"))
    # }}}

    # {{{ check RELATE_SESSION_RESTART_COOLDOWN_SECONDS
    relate_session_restart_cooldown_seconds = getattr(
        settings, RELATE_SESSION_RESTART_COOLDOWN_SECONDS, None)
    if relate_session_restart_cooldown_seconds is not None:
        if not isinstance(relate_session_restart_cooldown_seconds,
                          (int, float)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_SESSION_RESTART_COOLDOWN_SECONDS,
                        "types": "int or float"
                    }),
                    id="relate_session_restart_cooldown_seconds.E001"))
        else:
            if relate_session_restart_cooldown_seconds < 0:
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%(location)s must be a positive number, "
                             "got %(value)s instead" % {
                                 "location":
                                 RELATE_SESSION_RESTART_COOLDOWN_SECONDS,
                                 "value":
                                 relate_session_restart_cooldown_seconds
                             }),
                        id="relate_session_restart_cooldown_seconds.E002"))

    # }}}

    # {{{ check RELATE_TICKET_MINUTES_VALID_AFTER_USE
    relate_ticket_minutes_valid_after_use = getattr(
        settings, RELATE_TICKET_MINUTES_VALID_AFTER_USE, None)
    if relate_ticket_minutes_valid_after_use is not None:
        if not isinstance(relate_ticket_minutes_valid_after_use, (int, float)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_TICKET_MINUTES_VALID_AFTER_USE,
                        "types": "int or float"
                    }),
                    id="relate_ticket_minutes_valid_after_use.E001"))
        else:
            if relate_ticket_minutes_valid_after_use < 0:
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%(location)s must be a positive number, "
                             "got %(value)s instead" % {
                                 "location":
                                 RELATE_TICKET_MINUTES_VALID_AFTER_USE,
                                 "value": relate_ticket_minutes_valid_after_use
                             }),
                        id="relate_ticket_minutes_valid_after_use.E002"))

    # }}}

    # {{{ check GIT_ROOT
    git_root = getattr(settings, GIT_ROOT, None)
    if git_root is None:
        errors.append(
            RelateCriticalCheckMessage(msg=REQUIRED_CONF_ERROR_PATTERN %
                                       {"location": GIT_ROOT},
                                       id="git_root.E001"))
    elif not isinstance(git_root, str):
        errors.append(
            RelateCriticalCheckMessage(msg=INSTANCE_ERROR_PATTERN % {
                "location": GIT_ROOT,
                "types": "str"
            },
                                       id="git_root.E002"))
    else:
        if not os.path.isdir(git_root):
            errors.append(
                RelateCriticalCheckMessage(msg=(
                    "`%(path)s` configured in %(location)s is not a valid path"
                    % {
                        "path": git_root,
                        "location": GIT_ROOT
                    }),
                                           id="git_root.E003"))
        else:
            if not os.access(git_root, os.W_OK):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "`%(path)s` configured in %(location)s is not writable "
                        "by RELATE" % {
                            "path": git_root,
                            "location": GIT_ROOT
                        }),
                                               id="git_root.E004"))
            if not os.access(git_root, os.R_OK):
                errors.append(
                    RelateCriticalCheckMessage(msg=(
                        "`%(path)s` configured in %(location)s is not readable "
                        "by RELATE" % {
                            "path": git_root,
                            "location": GIT_ROOT
                        }),
                                               id="git_root.E005"))

    # }}}

    # {{{ check RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION
    relate_disable_codehilite_markdown_extension = getattr(
        settings, RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION, None)
    if relate_disable_codehilite_markdown_extension is not None:
        if not isinstance(relate_disable_codehilite_markdown_extension, bool):
            errors.append(
                Warning(
                    msg="%(location)s is not a Boolean value: `%(value)s`, "
                    "assuming True" % {
                        "location":
                        RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
                        "value":
                        repr(relate_disable_codehilite_markdown_extension)
                    },
                    id="relate_disable_codehilite_markdown_extension.W001"))
        elif not relate_disable_codehilite_markdown_extension:
            errors.append(
                Warning(
                    msg="%(location)s is set to False "
                    "(with 'markdown.extensions.codehilite' enabled'), "
                    "noticing that some pages with code fence markdown "
                    "might get crashed" % {
                        "location":
                        RELATE_DISABLE_CODEHILITE_MARKDOWN_EXTENSION,
                        "value":
                        repr(relate_disable_codehilite_markdown_extension)
                    },
                    id="relate_disable_codehilite_markdown_extension.W002"))

    # }}}

    # {{{ check LANGUAGES, why this is not done in django?

    languages = settings.LANGUAGES

    from django.utils.itercompat import is_iterable

    if (isinstance(languages, six.string_types) or not is_iterable(languages)):
        errors.append(
            RelateCriticalCheckMessage(
                msg=(INSTANCE_ERROR_PATTERN % {
                    "location": LANGUAGES,
                    "types": "an iterable (e.g., a list or tuple)."
                }),
                id="relate_languages.E001"))
    else:
        if any(
                isinstance(choice, six.string_types) or not is_iterable(choice)
                or len(choice) != 2 for choice in languages):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=("'%s' must be an iterable containing "
                         "(language code, language description) tuples, just "
                         "like the format of LANGUAGES setting ("
                         "https://docs.djangoproject.com/en/dev/ref/settings/"
                         "#languages)" % LANGUAGES),
                    id="relate_languages.E002"))
        else:
            from collections import OrderedDict
            options_dict = OrderedDict(tuple(settings.LANGUAGES))
            all_lang_codes = [
                lang_code
                for lang_code, lang_descr in tuple(settings.LANGUAGES)
            ]
            for lang_code in options_dict.keys():
                if all_lang_codes.count(lang_code) > 1:
                    errors.append(
                        Warning(msg=(
                            "Duplicate language entries were found in "
                            "settings.LANGUAGES for '%s', '%s' will be used "
                            "as its language_description" %
                            (lang_code, options_dict[lang_code])),
                                id="relate_languages.W001"))

    # }}}

    # {{{ check RELATE_SITE_NAME
    try:
        site_name = settings.RELATE_SITE_NAME
        if site_name is None:
            errors.append(
                RelateCriticalCheckMessage(msg=("%s must not be None" %
                                                RELATE_SITE_NAME),
                                           id="relate_site_name.E002"))
        else:
            if not isinstance(site_name, six.string_types):
                errors.append(
                    RelateCriticalCheckMessage(msg=(INSTANCE_ERROR_PATTERN % {
                        "location":
                        "%s/%s" %
                        (RELATE_SITE_NAME, RELATE_CUTOMIZED_SITE_NAME),
                        "types":
                        "string"
                    }),
                                               id="relate_site_name.E003"))
            elif not site_name.strip():
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("%s must not be an empty string" %
                             RELATE_SITE_NAME),
                        id="relate_site_name.E004"))
    except AttributeError:
        # This happens when RELATE_SITE_NAME is DELETED from settings.
        errors.append(
            RelateCriticalCheckMessage(msg=(REQUIRED_CONF_ERROR_PATTERN % {
                "location": RELATE_SITE_NAME
            }),
                                       id="relate_site_name.E001"))
    # }}}

    # {{{ check RELATE_OVERRIDE_TEMPLATES_DIRS

    relate_override_templates_dirs = getattr(settings,
                                             RELATE_OVERRIDE_TEMPLATES_DIRS,
                                             None)
    if relate_override_templates_dirs is not None:
        if (isinstance(relate_override_templates_dirs, six.string_types)
                or not is_iterable(relate_override_templates_dirs)):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_OVERRIDE_TEMPLATES_DIRS,
                        "types": "an iterable (e.g., a list or tuple)."
                    }),
                    id="relate_override_templates_dirs.E001"))
        else:
            if any(not isinstance(directory, six.string_types)
                   for directory in relate_override_templates_dirs):
                errors.append(
                    RelateCriticalCheckMessage(
                        msg=("'%s' must contain only string of paths." %
                             RELATE_OVERRIDE_TEMPLATES_DIRS),
                        id="relate_override_templates_dirs.E002"))
            else:
                for directory in relate_override_templates_dirs:
                    if not os.path.isdir(directory):
                        errors.append(
                            Warning(msg=(
                                "Invalid Templates Dirs item '%s' in '%s', "
                                "it will be ignored." %
                                (directory, RELATE_OVERRIDE_TEMPLATES_DIRS)),
                                    id="relate_override_templates_dirs.W001"))

    # }}}

    # {{{ check RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE
    relate_custom_page_types_removed_deadline = getattr(
        settings, RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE, None)
    if relate_custom_page_types_removed_deadline is not None:
        from datetime import datetime
        if not isinstance(relate_custom_page_types_removed_deadline, datetime):
            errors.append(
                RelateCriticalCheckMessage(
                    msg=(INSTANCE_ERROR_PATTERN % {
                        "location": RELATE_CUSTOM_PAGE_TYPES_REMOVED_DEADLINE,
                        "types": "datetime.datetime"
                    }),
                    id="relate_custom_page_types_removed_deadline.E001"))

    # }}}
    return errors
Ejemplo n.º 19
0
def check_panels_in_model(cls, context="model"):
    """Check panels configuration uses `panels` when `edit_handler` not in use."""
    from wagtail.admin.panels import InlinePanel, PanelGroup
    from wagtail.models import Page

    errors = []

    if hasattr(cls, "get_edit_handler"):
        # must check the InlinePanel related models
        edit_handler = cls.get_edit_handler()
        for tab in edit_handler.children:
            if isinstance(tab, PanelGroup):
                inline_panel_children = [
                    panel for panel in tab.children
                    if isinstance(panel, InlinePanel)
                ]
                for inline_panel_child in inline_panel_children:
                    errors.extend(
                        check_panels_in_model(
                            inline_panel_child.db_field.related_model,
                            context="InlinePanel model",
                        ))

    if issubclass(cls, Page) or hasattr(cls, "edit_handler"):
        # Pages do not need to be checked for standalone tabbed_panel usage
        # if edit_handler is used on any model, assume config is correct
        return errors

    tabbed_panels = [
        "content_panels",
        "promote_panels",
        "settings_panels",
    ]

    for panel_name in tabbed_panels:
        class_name = cls.__name__
        if not hasattr(cls, panel_name):
            continue

        panel_name_short = panel_name.replace("_panels", "").title()
        error_title = "{}.{} will have no effect on {} editing".format(
            class_name, panel_name, context)

        if "InlinePanel" in context:
            error_hint = """Ensure that {} uses `panels` instead of `{}`.
There are no tabs on non-Page model editing within InlinePanels.""".format(
                class_name, panel_name)
        else:
            error_hint = """Ensure that {} uses `panels` instead of `{}`\
or set up an `edit_handler` if you want a tabbed editing interface.
There are no default tabs on non-Page models so there will be no \
{} tab for the {} to render in.""".format(class_name, panel_name,
                                          panel_name_short, panel_name)

        error = Warning(error_title,
                        hint=error_hint,
                        obj=cls,
                        id="wagtailadmin.W002")

        errors.append(error)

    return errors
Ejemplo n.º 20
0
from django.core.checks import register, Error, Warning
from django.conf import settings
from django import apps

E001 = Error('DEBUG_PROPAGATE_EXCEPTIONS is still True.',
             id='preflight_debug.E001')

W001 = Warning('Debug toolbar is installed.', id='preflight_debug.W001')

W002 = Warning('Debug toolbar is activated.', id='preflight_debug.W002')


# noinspection PyUnusedLocal
@register('preflight', deploy=True)
def check_debug(app_configs, **kwargs):
    errors = []

    if settings.DEBUG_PROPAGATE_EXCEPTIONS:
        errors.append(E001)

    # Get all configs if we don't get a specific set
    if not app_configs:
        app_configs = apps.apps.app_configs.values()

    # Check for debug toolbar
    debug_toolbar = list(
        filter(lambda app: app.name == "debug_toolbar", app_configs))
    if debug_toolbar:
        errors.append(W001)

        if hasattr(settings, 'DEBUG_TOOLBAR_PATCH_SETTINGS'
Ejemplo n.º 21
0
    def check_custom_full_name_method(self):
        self._custom_full_name_method = None
        errors = []

        from django.conf import settings
        relate_user_full_name_format_method = getattr(
            settings, RELATE_USER_FULL_NAME_FORMAT_METHOD, None)

        if relate_user_full_name_format_method is None:
            return errors

        if isinstance(relate_user_full_name_format_method, six.string_types):
            try:
                relate_user_full_name_format_method = (
                    import_string(relate_user_full_name_format_method))
            except ImportError:
                errors = [
                    Warning(msg=(
                        "%(location)s: `%(method)s` failed to be imported, "
                        "default format method will be used." % {
                            "location": RELATE_USER_FULL_NAME_FORMAT_METHOD,
                            "method": relate_user_full_name_format_method
                        }),
                            id="relate_user_full_name_format_method.W001")
                ]
                return errors

        self._custom_full_name_method = relate_user_full_name_format_method
        if not callable(relate_user_full_name_format_method):
            errors.append(
                Warning(
                    msg=("%(location)s: `%(method)s` is not a callable, "
                         "default format method will be used." % {
                             "location": RELATE_USER_FULL_NAME_FORMAT_METHOD,
                             "method": relate_user_full_name_format_method
                         }),
                    id="relate_user_full_name_format_method.W002"))
        else:
            try:
                returned_name = (relate_user_full_name_format_method(
                    "first_name", "last_name"))
            except Exception as e:
                from traceback import format_exc
                errors.append(
                    Warning(msg=(
                        "%(location)s: `%(method)s` called with '"
                        "args 'first_name', 'last_name' failed with"
                        "exception below:\n"
                        "%(err_type)s: %(err_str)s\n"
                        "%(format_exc)s\n\n"
                        "Default format method will be used." % {
                            "location": RELATE_USER_FULL_NAME_FORMAT_METHOD,
                            "method": relate_user_full_name_format_method,
                            "err_type": type(e).__name__,
                            "err_str": str(e),
                            'format_exc': format_exc()
                        }),
                            id="relate_user_full_name_format_method.W003"))
            else:
                unexpected_return_value = ""
                if returned_name is None:
                    unexpected_return_value = "None"
                if not isinstance(returned_name, six.string_types):
                    unexpected_return_value = type(returned_name).__name__
                elif not returned_name.strip():
                    unexpected_return_value = "empty string %s" % returned_name
                if unexpected_return_value:
                    errors.append(
                        Warning(msg=(
                            "%(location)s: `%(method)s` is expected to "
                            "return a non-empty string, got `%(result)s`, "
                            "default format method will be used." % {
                                "location":
                                RELATE_USER_FULL_NAME_FORMAT_METHOD,
                                "method": relate_user_full_name_format_method,
                                "result": unexpected_return_value,
                            }),
                                id="relate_user_full_name_format_method.W004"))
                else:
                    returned_name2 = (relate_user_full_name_format_method(
                        "first_name2", "last_name2"))
                    if returned_name == returned_name2:
                        errors.append(
                            Warning(
                                msg=
                                ("%(location)s: `%(method)s` is expected to "
                                 "return different value with different "
                                 "input, default format method will be used." %
                                 {
                                     "location":
                                     RELATE_USER_FULL_NAME_FORMAT_METHOD,
                                     "method":
                                     relate_user_full_name_format_method
                                 }),
                                id="relate_user_full_name_format_method.W005"))

        if errors:
            self._custom_full_name_method = None

        return errors
Ejemplo n.º 22
0
def create_warning_1_multiple_features_in_concent_feature() -> Warning:
    return Warning(
        'Some features appear multiple times in CONCENT_FEATURES setting',
        hint='Remove the duplicate names.',
        id='concent.W001',
    )
Ejemplo n.º 23
0
 def warning(self, title, **kwargs):
     kwargs.setdefault('obj', self.config.label)
     kwargs.setdefault('id', self.id)
     return Warning(title, **kwargs)
Ejemplo n.º 24
0
def custom_warning_system_check(app_configs, **kwargs):
    return [Warning("Warning", id="mywarningcheck.E001")]
Ejemplo n.º 25
0
def best_practice(app_configs, **kwargs):
    """
    Test for configuration recommendations. These are best practices, they
    avoid hard to find bugs and unexpected behaviour.
    """
    if app_configs is None:
        app_configs = apps.get_app_configs()

    # Take the app_configs and turn them into *old style* application names.
    # This is what we expect in the SHARED_APPS and TENANT_APPS settings.
    INSTALLED_APPS = [config.name for config in app_configs]

    if not hasattr(settings, 'TENANT_APPS'):
        return [Critical('TENANT_APPS setting not set')]

    if not hasattr(settings, 'TENANT_MODEL'):
        return [Critical('TENANT_MODEL setting not set')]

    if not hasattr(settings, 'SHARED_APPS'):
        return [Critical('SHARED_APPS setting not set')]

    if 'tenant_schemas.routers.TenantSyncRouter' not in settings.DATABASE_ROUTERS:
        return [
            Critical("DATABASE_ROUTERS setting must contain "
                     "'tenant_schemas.routers.TenantSyncRouter'.")
        ]

    errors = []

    if INSTALLED_APPS[0] != 'tenant_schemas':
        errors.append(
            Warning("You should put 'tenant_schemas' first in INSTALLED_APPS.",
                    obj="django.conf.settings",
                    hint="This is necessary to overwrite built-in django "
                    "management commands with their schema-aware "
                    "implementations."))

    if not settings.TENANT_APPS:
        errors.append(
            Error("TENANT_APPS is empty.",
                  hint="Maybe you don't need this app?"))

    if hasattr(settings, 'PG_EXTRA_SEARCH_PATHS'):
        if get_public_schema_name() in settings.PG_EXTRA_SEARCH_PATHS:
            errors.append(
                Critical("%s can not be included on PG_EXTRA_SEARCH_PATHS." %
                         get_public_schema_name()))

        # make sure no tenant schema is in settings.PG_EXTRA_SEARCH_PATHS
        invalid_schemas = set(settings.PG_EXTRA_SEARCH_PATHS).intersection(
            get_tenant_model().objects.all().values_list('schema_name',
                                                         flat=True))
        if invalid_schemas:
            errors.append(
                Critical(
                    "Do not include tenant schemas (%s) on PG_EXTRA_SEARCH_PATHS."
                    % ", ".join(sorted(invalid_schemas))))

    if not settings.SHARED_APPS:
        errors.append(Warning("SHARED_APPS is empty."))

    if not set(settings.TENANT_APPS).issubset(INSTALLED_APPS):
        delta = set(settings.TENANT_APPS).difference(INSTALLED_APPS)
        errors.append(
            Error("You have TENANT_APPS that are not in INSTALLED_APPS",
                  hint=[a for a in settings.TENANT_APPS if a in delta]))

    if not set(settings.SHARED_APPS).issubset(INSTALLED_APPS):
        delta = set(settings.SHARED_APPS).difference(INSTALLED_APPS)
        errors.append(
            Error("You have SHARED_APPS that are not in INSTALLED_APPS",
                  hint=[a for a in settings.SHARED_APPS if a in delta]))

    return errors
Ejemplo n.º 26
0
def microsoft_auth_validator(app_configs, **kwargs):
    from django.contrib.sites.models import Site
    from .conf import config

    errors = []

    if apps.is_installed("microsoft_auth"
                         ) and not apps.is_installed("django.contrib.sites"):

        errors.append(
            Critical(
                "`django.contrib.sites` is not installed",
                hint=("`microsoft_auth` requires `django.contrib.sites` "
                      "to be installed and configured"),
                id="microsoft_auth.E001",
            ))

    if not hasattr(config, "SITE_ID") or config.SITE_ID is None:
        errors.append(
            Critical(
                "current site not configured",
                hint=("`django.contrib.sites` requires a `SITE_ID` setting "
                      "to be set"),
                id="microsoft_auth.E002",
            ))
    else:
        try:
            current_site = Site.objects.get_current()
        except OperationalError:
            errors.append(
                Warning(
                    "`django.contrib.sites` migrations not ran",
                    id="microsoft_auth.W001",
                ))
        else:
            if str(current_site) == "example.com":
                errors.append(
                    Warning(
                        ("current site is still `example.com`, Microsoft "
                         "auth might not work"),
                        hint=("Microsoft/Xbox auth uses OAuth, which requires "
                              "a real redirect URI to come back to"),
                        id="microsoft_auth.W002",
                    ))

    if config.MICROSOFT_AUTH_LOGIN_ENABLED:  # pragma: no branch
        if config.MICROSOFT_AUTH_CLIENT_ID == "":
            errors.append(
                Warning(
                    ("`MICROSOFT_AUTH_CLIENT_ID` is not configured"),
                    hint=("`MICROSOFT_AUTH_LOGIN_ENABLED` is `True`, but "
                          "`MICROSOFT_AUTH_CLIENT_ID` is empty. Microsoft "
                          "auth will be disabled"),
                    id="microsoft_auth.W003",
                ))
        if config.MICROSOFT_AUTH_CLIENT_SECRET == "":
            errors.append(
                Warning(
                    ("`MICROSOFT_AUTH_CLIENT_SECRET` is not configured"),
                    hint=("`MICROSOFT_AUTH_LOGIN_ENABLED` is `True`, but "
                          "`MICROSOFT_AUTH_CLIENT_SECRET` is empty. Microsoft "
                          "auth will be disabled"),
                    id="microsoft_auth.W004",
                ))

    return errors
Ejemplo n.º 27
0
def compat_check(app_configs=None, **kwargs):
    errors = []

    # Imports first
    try:
        import pymongo
        have_mongo = True
    except ImportError:
        have_mongo = False
        errors.append(
            Error('Unable to import pymongo', hint='sudo pip install pymongo'))

    try:
        from virus_total_apis import PublicApi
    except ImportError:
        errors.append(
            Warning('Unable to import virustotalapi',
                    hint='sudo pip install virustotal'))

    try:
        import yara
    except ImportError:
        errors.append(
            Warning('Unable to import Yara',
                    hint='Read the Wiki or google Yara'))

    try:
        import distorm3
    except ImportError:
        errors.append(
            Warning('Unable to import distorm3',
                    hint='sudo pip install distorm3'))

    # Check Vol Version

    try:
        vol_ver = vol_interface.vol_version.split('.')
        if int(vol_ver[1]) < 5:
            errors.append(
                Error(
                    'Unsupported Volatility version found. Need 2.5 or greater. Found: {0}'
                    .format('.'.join(vol_ver))))
    except Exception as error:
        errors.append(
            Error('Unable to find Volatility Version Number',
                  hint='Read the installation wiki'))

    # Config
    try:
        from common import Config
        config = Config()
        if config.valid:
            pass

    except:
        errors.append(
            Error('Unable to parse a volutility.conf file',
                  hint='Copy volutiltiy.conf.sample to volutitliy.conf'))

    # Database Connection finally
    if have_mongo:
        try:
            connection = pymongo.MongoClient('localhost')

            # Version Check
            server_version = connection.server_info()['version']

            if int(server_version[0]) < 3:
                errors.append(
                    Error(
                        str('Incompatible MongoDB Version detected. Requires 3 or higher. Found {0}'
                            .format(server_version))))

            connection.close()

        except Exception as error:
            errors.append(
                Error('Unable to connect to MongoDB: {0}'.format(error)))

    return errors
Ejemplo n.º 28
0
def api_struct_check(app_configs, **kwargs):
    from rest_models.backend.compiler import get_resource_path  # NOQA
    from rest_models.router import RestModelRouter  # NOQA

    errors = []

    all_models = []
    if app_configs is None:
        all_models.extend(apps.get_models())
    else:
        for app_config in app_configs:
            all_models.extend(app_config.get_models())
    router = RestModelRouter()
    models = ((router.get_api_connexion(model).cursor(), model)
              for model in all_models
              if router.is_api_model(model) and not bool(
                  router.get_api_connexion(model).settings_dict['OPTIONS'].get(
                      'SKIP_CHECK', False)))

    for db, rest_model in models:
        url = get_resource_path(rest_model)
        res = db.options(url)
        if res.status_code != 200:
            errors.append(
                Error(
                    'the remote api does not respond to us. OPTIONS %s%s => %s'
                    % (db.url, url, res.status_code),
                    hint=
                    'check the url for the remote api or the resource_path',
                    obj=rest_model,
                    id='rest_models.E001'))
            continue
        options = res.json()
        missings = {
            'include[]', 'exclude[]', 'filter{}', 'page', 'per_page', 'sort[]'
        } - set(options.get("features", []))
        if missings:
            errors.append(
                Error(
                    'the remote api does not support the folowing features: %s'
                    % missings,
                    hint='is the api on %s/%s running with dynamic-rest ?' %
                    (db.url, url),
                    obj=rest_model,
                    id='rest_models.E002'))
            continue
        for field in rest_model._meta.get_fields():
            field_name = field.concrete and field.db_column or field.name
            if field.is_relation:
                if router.is_api_model(field.related_model):
                    if field_name not in options['properties']:
                        errors.append(
                            Error(
                                'the field %s.%s in not present on the remote serializer'
                                % (rest_model.__name__, field_name),
                                obj="%s.%s" %
                                (rest_model.__name__, field_name),
                                hint=
                                'check if the serializer on %s/%s has a field "%s"'
                                % (db.url, url, field_name),
                                id='rest_models.E003'))
                    else:
                        type_is_many = options['properties'][field_name][
                            'type'] == 'many'
                        type_is_one = options['properties'][field_name][
                            'type'] == 'one'
                        if (type_is_many and
                                not (field.one_to_many or field.many_to_many)
                                or type_is_one and
                                not (field.one_to_one or field.many_to_one)):

                            errors.append(
                                Error(
                                    'the field %s.%s many does not match the api'
                                    % (rest_model.__name__, field_name),
                                    obj="%s.%s" %
                                    (rest_model.__name__, field_name),
                                    hint=
                                    'check if the serializer at %s%s have a Serializer.many '
                                    'value corresponding to the local model %s'
                                    % (db.url, url, field_name),
                                    id='rest_models.E005'))

                        choice_count = len(
                            options['properties'][field_name].get(
                                'choices', []))
                        if choice_count > 100:
                            errors.append(
                                Warning(
                                    'the field %s.%s has many choices values (%s) in OPTIONS '
                                    'and it slow down the check' %
                                    (rest_model.__name__, field_name,
                                     choice_count),
                                    obj="%s.%s" %
                                    (rest_model.__name__, field_name),
                                    hint=
                                    'check if the serializer at %s%s provide '
                                    'a choices with less values for %s' %
                                    (db.url, url, field_name),
                                    id='rest_models.W001'))

            elif field_name not in options['properties']:
                errors.append(
                    Error(
                        'the field %s.%s in not present on the remote serializer'
                        % (rest_model.__name__, field_name),
                        hint='check if the serializer on %s%s has a field "%s"'
                        % (db.url, url, field_name),
                        id='rest_models.E006'))
    return errors
Ejemplo n.º 29
0
def custom_warning_system_check(app_configs, **kwargs):
    return [Warning('Warning', id='mywarningcheck.E001')]
Ejemplo n.º 30
0
from django.core.checks import register, Warning
from django.template.loader import get_template, TemplateDoesNotExist

W001 = Warning(
    'You must add "admin_tools.template_loaders.Loader" in your '
    'template loaders variable, see: '
    'https://django-admin-tools.readthedocs.org/en/latest/configuration.html',
    id='admin_tools.W001',
    obj='admin_tools')


@register('admin_tools')
def check_admin_tools_configuration(app_configs=None, **kwargs):
    result = []
    try:
        get_template('admin:admin/base.html')
    except TemplateDoesNotExist:
        result.append(W001)
    return result