Exemplo n.º 1
0
class AWS:
    """AWS configuration"""
    # If you all you know is the queue *name* and its AWS region,
    # make the URL be:
    #   aws://https://sqs.$NAME_OF_REGION.amazonaws.com/$NAME_OF_QUEUE
    SQS_QUEUE_URL = values.URLValue(
        'https://sqs.us-west-2.amazonaws.com/927034868273/buildhub-s3-events')
    S3_BUCKET_URL = values.URLValue(
        'https://s3-us-west-2.amazonaws.com/buildhub-sqs-test')

    # For more details, see:
    # http://boto3.readthedocs.io/en/latest/reference/services/sqs.html#SQS.Queue.receive_messages

    # The duration (in seconds) for which the call waits for a message
    # to arrive in the queue before returning.
    SQS_QUEUE_WAIT_TIME_SECONDS = values.IntegerValue(10)

    # The duration (in seconds) that the received messages are hidden
    # from subsequent retrieve requests after being retrieved by
    # a ReceiveMessage request.
    # Note! This only really matters when multiple concurrent consumers run
    # daemons that consume the queue.
    SQS_QUEUE_VISIBILITY_TIMEOUT = values.IntegerValue(5)

    # The maximum number of messages to return.
    # Valid values are 1 to 10. Default is 1.
    SQS_QUEUE_MAX_NUMBER_OF_MESSAGES = values.IntegerValue(1)
Exemplo n.º 2
0
class AWS:
    """AWS configuration"""

    # If you all you know is the queue *name* and its AWS region,
    # make the URL be:
    #   aws://https://sqs.$NAME_OF_REGION.amazonaws.com/$NAME_OF_QUEUE
    SQS_QUEUE_URL = values.URLValue(
        "https://sqs.us-west-2.amazonaws.com/927034868273/buildhub-s3-events")
    S3_BUCKET_URL = values.URLValue(
        "https://s3-us-east-1.amazonaws.com/"
        "net-mozaws-prod-delivery-inventory-us-east-1")

    # For more details, see:
    # http://boto3.readthedocs.io/en/latest/reference/services/sqs.html#SQS.Queue.receive_messages

    # The duration (in seconds) for which the call waits for a message
    # to arrive in the queue before returning.
    SQS_QUEUE_WAIT_TIME_SECONDS = values.IntegerValue(10)

    # The duration (in seconds) that the received messages are hidden
    # from subsequent retrieve requests after being retrieved by
    # a ReceiveMessage request.
    # Note! This only really matters when multiple concurrent consumers run
    # daemons that consume the queue.
    SQS_QUEUE_VISIBILITY_TIMEOUT = values.IntegerValue(5)

    # The maximum number of messages to return.
    # Valid values are 1 to 10. Default is 1.
    SQS_QUEUE_MAX_NUMBER_OF_MESSAGES = values.IntegerValue(1)

    # When we ingest the SQS queue we get a payload that contains an S3 key and
    # a S3 bucket name. We then assume that we can use our boto client to connect
    # to that bucket to read the key to download its file. That S3 bucket name
    # comes at runtime so it depends on the payloads which aren't know yet.
    # However, if you *do* know the bucket set this variable in advance so access
    # to it can be healthchecked.
    # Note that it's optional! Unset by default.
    # In real product it should probably be:
    #  https://s3.amazonaws.com/net-mozaws-prod-delivery-firefox
    SQS_S3_BUCKET_URL = values.URLValue()

    # If, the S3 bucket that SQS mentioned by name is a public you can connect
    # to is with an unsigned client. If you don't do this, the request might
    # fail with:
    #   "An error occurred (403) when calling the HeadObject operation: Forbidden"
    # If however, like during local development, you use a non-public bucket this
    # need to be set to false.
    UNSIGNED_SQS_S3_CLIENT = values.BooleanValue(True)
Exemplo n.º 3
0
class DandiMixin(ConfigMixin):
    WSGI_APPLICATION = 'dandiapi.wsgi.application'
    ROOT_URLCONF = 'dandiapi.urls'

    BASE_DIR = Path(__file__).resolve(strict=True).parent.parent

    REST_FRAMEWORK_EXTENSIONS = {'DEFAULT_PARENT_LOOKUP_KWARG_NAME_PREFIX': ''}

    ACCOUNT_EMAIL_VERIFICATION = 'none'

    @staticmethod
    def before_binding(configuration: Type[ComposedConfiguration]):
        # Install local apps first, to ensure any overridden resources are found first
        configuration.INSTALLED_APPS = [
            'dandiapi.api.apps.PublishConfig',
        ] + configuration.INSTALLED_APPS

        # Install additional apps
        configuration.INSTALLED_APPS += [
            'guardian',
            'allauth.socialaccount.providers.github',
        ]

        configuration.AUTHENTICATION_BACKENDS += [
            'guardian.backends.ObjectPermissionBackend'
        ]
        configuration.REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] += [
            # TODO remove TokenAuthentication, it is only here to support
            # the setTokenHack login workaround
            'rest_framework.authentication.TokenAuthentication',
        ]
        configuration.REST_FRAMEWORK[
            'DEFAULT_PAGINATION_CLASS'] = 'dandiapi.api.views.common.DandiPagination'

    DANDI_DANDISETS_BUCKET_NAME = values.Value(environ_required=True)
    DANDI_GIRDER_API_URL = values.URLValue(environ_required=True)
    DANDI_GIRDER_API_KEY = values.Value(environ_required=True)
    DANDI_SCHEMA_VERSION = values.Value(environ_required=True)

    DANDI_DOI_API_URL = values.URLValue(environ=True)
    DANDI_DOI_API_USER = values.Value(environ=True)
    DANDI_DOI_API_PASSWORD = values.Value(environ=True)
    DANDI_DOI_API_PREFIX = values.Value(environ=True)

    # The CloudAMQP connection was dying, using the heartbeat should keep it alive
    CELERY_BROKER_HEARTBEAT = 20
Exemplo n.º 4
0
 def RAVEN_CONFIG(self):
     return {
         'dsn':
         values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
         'string_max_length':
         values.IntegerValue(2000,
                             environ_name='RAVEN_CONFIG_STRING_MAX_LENGTH')
     }
Exemplo n.º 5
0
class Raven(object):
    """Report uncaught exceptions to the Sentry server."""

    INSTALLED_APPS = common.Common.INSTALLED_APPS + ('raven.contrib.django.raven_compat',)

    RAVEN_CONFIG = {
        'dsn': values.URLValue(environ_name='RAVEN_CONFIG_DSN'),
        'release': __version__,
    }
Exemplo n.º 6
0
class OIDC:
    """Settings related to talking to an OIDC provider for authorizing
    access tokens received from the client."""

    # Note! We *could* just have a setting called 'OIDC_DOMAIN' and then use
    # https://$OIDC_DOMAIN/.well-known/openid-configuration and extract the
    # 'userinfo_endpoint' value from that during startup or something.
    # As of May 2018, the likelyhood of this URL changing and the fact that it's
    # the only URL we need, let's just make the setting the URL that we need
    # for being able to authorization by access token.
    OIDC_USER_ENDPOINT = values.URLValue("https://auth.mozilla.auth0.com/userinfo")
class Prod(Base):
    DEBUG = False

    INSTALLED_APPS = Base.INSTALLED_APPS + [
        'raven.contrib.django.raven_compat',
    ]

    RAVEN_CONFIG = {
        'dsn': values.URLValue(environ_name='SENTRY_DSN'),
        'release': Base.VERSION,
        'environment': 'production',
    }
Exemplo n.º 8
0
class Dev(Base):
    """Base settings for development."""

    DEBUG = True

    # Required overrides
    SITE_URL = values.URLValue('http://*****:*****@example.com',
        'password': '******'
    })

    # Storage
    AWS_S3_REGION_NAME = ''
    AWS_STORAGE_BUCKET_NAME = values.Value('django')
    AWS_S3_ENDPOINT_URL = values.Value('http://minio:9000')
    AWS_ACCESS_KEY_ID = values.Value('djangos3')
    AWS_SECRET_ACCESS_KEY = values.Value('djangos3')
    AWS_S3_SECURE_URLS = values.BooleanValue(True)

    @property
    def AWS_S3_CUSTOM_DOMAIN(self):
        return values.Value(self.URL.netloc)

    # Core
    @property
    def FRONTEND_URL(self):
        return values.URLValue(self.SITE_URL)

    @property
    def INSTALLED_APPS(self):
        return super().INSTALLED_APPS + [
            'debug_toolbar',
        ]

    # Security
    CORS_ORIGIN_ALLOW_ALL = True
    SESSION_COOKIE_SECURE = False
    CSRF_COOKIE_SECURE = False
    AWS_AUTO_CREATE_BUCKET = True

    # Email
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

    # Services
    CELERY_BROKER_URL = values.Value('redis://redis',
                                     environ_name='CELERY_BROKER_URL')
    DATABASES = values.DatabaseURLValue(
        'postgis://*****:*****@db:5432/django')
Exemplo n.º 9
0
    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, '__version__', 'tag')
        try:
            with open(version_path) as f:
                version = f.read().strip()
        except IOError:
            version = None

        return {
            'dsn': values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
            'release': values.Value(version, environ_name='RAVEN_CONFIG_RELEASE'),
        }
Exemplo n.º 10
0
    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, "version.json")
        try:
            with open(version_path) as f:
                build_info = json.loads(f.read())
                version = build_info.get("version")
        except IOError:
            version = None

        return {
            "dsn": values.URLValue(None, environ_name="RAVEN_CONFIG_DSN"),
            "release": values.Value(version, environ_name="RAVEN_CONFIG_RELEASE"),
        }
Exemplo n.º 11
0
class BaseAuthConfigurationMixin:
    """
    Basic Mixin class which all django projects using this library should include
    """

    MAFIASI_AUTH_APPS = ["django_auth_mafiasi"]
    "List of apps which need to be added to django's " \
    "`INSTALLED_APPS <https://docs.djangoproject.com/en/3.1/ref/settings/#installed-apps>`_"

    AUTH_GET_USER_FROM_ID_TOKEN_FUNCTION = "django_auth_mafiasi.auth.get_user_from_id_token"
    "Import path of a function which is used when a user object needs to be derived from an OpenId **ID token**"

    AUTH_GET_USER_FROM_ACCESS_TOKEN_FUNCTION = "django_auth_mafiasi.auth.get_user_from_access_token"
    "Import path of a function which is used when a user object needs to be derived from an OpenId **access token**"

    AUTH_USER_MODEL = "django_auth_mafiasi.MafiasiAuthModelUser"
    "See `django documentation <https://docs.djangoproject.com/en/3.1/ref/settings/#auth-user-model>`_." \
    "If you override this, your new model should inherit from MafiasiAuthModelUser"

    AUTH_SERVER = values.URLValue(default="https://identity.mafiasi.de/auth/realms/mafiasi")
    "OpenId Issuer. This defaults to our Mafiasi server but theoretically, any OpenId Issuer can be used"

    AUTH_CLIENT_ID = values.Value(environ_required=True)
    "OpenId client id\n\n" \
    "It needs to be manually retrieved from the OpenId server and uniquely identifies this application"

    AUTH_CLIENT_SECRET = values.SecretValue(environ_required=True)
    "OpenId client secret\n\n" \
    "It needs to be manually retrieved from the OpenId server and authenticates this application (not the user)"

    AUTH_SCOPE = values.ListValue(default=["openid"])
    "Scopes to request when logging a user in on the OpenId provider"

    AUTH_STAFF_GROUPS = values.ListValue(default=["Server-AG"])
    "Which groups are considered to be staff (have access to the admin panel)"

    AUTH_SUPERUSER_GROUPS = values.ListValue(default=["Server-AG"])
    "Which groups are considered to be superusers (have access to everything)"

    REST_FRAMEWORK_REQUIRED_SCOPES = values.ListValue(default=["openid"])
    "Scopes to which an access token needs to have access to in order to be allowed access the an API secured by the rest framework authenticator"

    LOGIN_REDIRECT_URL = "/"
    "Where to redirect a user after successful login"

    LOGOUT_REDIRECT_URL = "/"
    "Where to redirect a user after logout"

    LOGIN_URL = "django_auth_mafiasi:login"
Exemplo n.º 12
0
class DandiConfig(ConfigMixin):
    WSGI_APPLICATION = 'dandi.wsgi.application'
    ROOT_URLCONF = 'dandi.urls'

    BASE_DIR = str(Path(__file__).absolute().parent.parent)

    REST_FRAMEWORK_EXTENSIONS = {'DEFAULT_PARENT_LOOKUP_KWARG_NAME_PREFIX': ''}

    @staticmethod
    def before_binding(configuration: Type[ComposedConfiguration]):
        configuration.INSTALLED_APPS += ['dandi.publish.apps.PublishConfig']

    DANDI_DANDISETS_BUCKET_NAME = values.Value(environ_required=True)
    DANDI_GIRDER_API_URL = values.URLValue(environ_required=True)
    DANDI_GIRDER_API_KEY = values.Value(environ_required=True)
Exemplo n.º 13
0
class Production(Common):
    @property
    def JWT_AUTH(self):
        return get_jwt_auth()

    DEBUG = False
    TEMPLATE_DEBUG = DEBUG

    PAGE_CACHE_SECONDS = values.IntegerValue(1)

    # TODO: n a real production server this should have a proper url
    ALLOWED_HOSTS = values.ListValue(['getfission.com'])

    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = values.SecretValue()

    # ########### Sentry configuration
    RAVEN_DSN = values.URLValue()

    RAVEN_CONFIG = {'dsn': os.environ.get('RAVEN_DSN')}
Exemplo n.º 14
0
class Base(Core):
    """Configuration that may change per-environment, some with defaults."""

    SECRET_KEY = values.SecretValue()

    DEBUG = values.BooleanValue(default=False)

    ALLOWED_HOSTS = values.ListValue([])

    #: The URL under which this instance is running
    SITE_URL = values.URLValue("http://*****:*****@db/postgres")

    REDIS_URL_DEFAULT = "redis://redis:6379/1"
    CACHES = EnvironCacheURLValue(
        REDIS_URL_DEFAULT, environ_prefix=None, environ_name="REDIS_URL"
    )
    # Use redis as the Celery broker.
    CELERY_BROKER_URL = os.environ.get("REDIS_URL", REDIS_URL_DEFAULT)

    LOGGING_USE_JSON = values.BooleanValue(False)

    OIDC_RP_CLIENT_ID = values.Value(
        environ_name="OIDC_RP_CLIENT_ID", environ_prefix=None
    )
    OIDC_RP_CLIENT_SECRET = values.Value(
        environ_name="OIDC_RP_CLIENT_SECRET", environ_prefix=None
    )
    OIDC_OP_AUTHORIZATION_ENDPOINT = values.Value(
        environ_name="OIDC_OP_AUTHORIZATION_ENDPOINT", environ_prefix=None
    )
    OIDC_OP_TOKEN_ENDPOINT = values.Value(
        environ_name="OIDC_OP_TOKEN_ENDPOINT", environ_prefix=None
    )
    OIDC_OP_USER_ENDPOINT = values.Value(
        environ_name="OIDC_OP_USER_ENDPOINT", environ_prefix=None
    )
    OIDC_OP_DOMAIN = values.Value(environ_name="OIDC_OP_DOMAIN", environ_prefix=None)

    def LOGGING(self):
        return {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "json": {
                    "()": "dockerflow.logging.JsonLogFormatter",
                    "logger_name": "atmo",
                },
                "verbose": {"format": "%(levelname)s %(asctime)s %(name)s %(message)s"},
                "django.server": {
                    "()": "django.utils.log.ServerFormatter",
                    "format": "[%(server_time)s] %(message)s",
                },
            },
            "handlers": {
                "console": {
                    "level": "DEBUG",
                    "class": "logging.StreamHandler",
                    "formatter": "json" if self.LOGGING_USE_JSON else "verbose",
                },
                "sentry": {
                    "level": "ERROR",
                    "class": "raven.contrib.django.raven_compat.handlers.SentryHandler",
                },
                "django.server": {
                    "level": "INFO",
                    "class": "logging.StreamHandler",
                    "formatter": "django.server",
                },
            },
            "loggers": {
                "root": {"level": "INFO", "handlers": ["sentry", "console"]},
                "django.db.backends": {
                    "level": "ERROR",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "django.server": {
                    "handlers": ["django.server"],
                    "level": "INFO",
                    "propagate": False,
                },
                "raven": {
                    "level": "DEBUG",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "sentry.errors": {
                    "level": "DEBUG",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "atmo": {"level": "DEBUG", "handlers": ["console"], "propagate": False},
                "celery.task": {
                    "level": "DEBUG",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "redbeat.schedulers": {
                    "level": "DEBUG",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "request.summary": {
                    "level": "DEBUG",
                    "handlers": ["console"],
                    "propagate": False,
                },
                "mozilla_django_oidc": {
                    "level": "INFO",
                    "handlers": ["console"],
                    "propagate": False,
                },
            },
        }
Exemplo n.º 15
0
class Base(Core):
    """Settings that may change per-environment, some with defaults."""

    # Flags that affect other settings, via setting methods below
    LOGGING_USE_JSON = values.BooleanValue(False)
    USE_OIDC = values.BooleanValue(False)

    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])
    SILENCED_SYSTEM_CHECKS = values.ListValue([
        # Check CSRF cookie http only. disabled because we read the
        # CSRF cookie in JS for forms in React.
        'security.W017',
    ])

    # Authentication
    def AUTHENTICATION_BACKENDS(self):
        if self.USE_OIDC:
            return ['normandy.base.auth_backends.LoggingRemoteUserBackend']
        else:
            return ['normandy.base.auth_backends.LoggingModelBackend']

    OIDC_REMOTE_AUTH_HEADER = values.Value('HTTP_REMOTE_USER')
    OIDC_LOGOUT_URL = values.Value(None)

    # Middleware that _most_ environments will need. Subclasses can override this list.
    EXTRA_MIDDLEWARE = [
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
    ]

    def MIDDLEWARE(self):
        """
        Determine middleware by combining the core set and
        per-environment set.
        """
        middleware = Core.MIDDLEWARE + self.EXTRA_MIDDLEWARE
        if self.USE_OIDC:
            middleware.append('normandy.base.middleware.ConfigurableRemoteUserMiddleware')
        return middleware

    def LOGGING(self):
        return {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'json': {
                    '()': 'mozilla_cloud_services_logger.formatters.JsonLogFormatter',
                    'logger_name': 'normandy',
                },
                'development': {
                    'format': '%(levelname)s %(asctime)s %(name)s %(message)s',
                },
            },
            'handlers': {
                'console': {
                    'level': 'DEBUG',
                    'class': 'logging.StreamHandler',
                    'formatter': 'json' if self.LOGGING_USE_JSON else 'development',
                },
            },
            'root': {
                'handlers': ['console'],
                'level': 'WARNING',
            },
            'loggers': {
                'normandy': {
                    'propagate': False,
                    'handlers': ['console'],
                    'level': 'DEBUG',
                },
                'request.summary': {
                    'propagate': False,
                    'handlers': ['console'],
                    'level': 'DEBUG',
                },
            },
        }

    # Remote services
    DATABASES = values.DatabaseURLValue('postgres://postgres@localhost/normandy')
    CONN_MAX_AGE = values.IntegerValue(0)
    GEOIP2_DATABASE = values.Value(os.path.join(Core.BASE_DIR, 'GeoLite2-Country.mmdb'))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value('django.core.mail.backends.smtp.EmailBackend')

    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, '__version__', 'tag')
        try:
            with open(version_path) as f:
                version = f.read().strip()
        except IOError:
            version = None

        return {
            'dsn': values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
            'release': values.Value(version, environ_name='RAVEN_CONFIG_RELEASE'),
        }

    # statsd
    STATSD_HOST = values.Value('localhost')
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value('normandy')
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    AUTH_PASSWORD_VALIDATORS = [
        {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
        {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
        {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
        {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
    ]
    PASSWORD_HASHERS = values.ListValue([
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(False)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value('DENY')
    REQUIRE_RECIPE_AUTH = values.BooleanValue(True)

    # Media and static settings
    STATIC_URL = values.Value('/static/')
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'static'))
    MEDIA_URL = values.Value('/media/')
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'media'))

    STATICFILES_DIRS = (
        os.path.join(Core.BASE_DIR, 'assets'),
    )

    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)
    # URL that bypasses any CDNs
    APP_SERVER_URL = values.URLValue(None)

    # URL for the CSP report-uri directive.
    CSP_REPORT_URI = values.Value('/__cspreport__')

    # Normandy settings
    ADMIN_ENABLED = values.BooleanValue(True)
    ACTION_IMPLEMENTATION_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)
    NUM_PROXIES = values.IntegerValue(0)
    API_CACHE_TIME = values.IntegerValue(30)
    API_CACHE_ENABLED = values.BooleanValue(True)

    # If true, approvals must come from two separate users. If false, the same
    # user can approve their own request.
    PEER_APPROVAL_ENFORCED = values.BooleanValue(True)

    # Autograph settings
    AUTOGRAPH_URL = values.Value()
    AUTOGRAPH_HAWK_ID = values.Value()
    AUTOGRAPH_HAWK_SECRET_KEY = values.Value()
    AUTOGRAPH_SIGNATURE_MAX_AGE = values.IntegerValue(60 * 60 * 24 * 7)
    AUTOGRAPH_X5U_CACHE_BUST = values.Value(None)

    # How many days before expiration to warn for expired certificates
    CERTIFICATES_EXPIRE_EARLY_DAYS = values.IntegerValue(None)

    PROD_DETAILS_DIR = values.Value(os.path.join(Core.BASE_DIR, 'product_details'))

    # AWS settings
    AWS_ACCESS_KEY_ID = values.Value()
    AWS_SECRET_ACCESS_KEY = values.Value()
    AWS_STORAGE_BUCKET_NAME = values.Value()

    GITHUB_URL = values.Value('https://github.com/mozilla/normandy')
Exemplo n.º 16
0
class DandiMixin(ConfigMixin):
    WSGI_APPLICATION = 'dandiapi.wsgi.application'
    ROOT_URLCONF = 'dandiapi.urls'

    BASE_DIR = Path(__file__).resolve(strict=True).parent.parent

    REST_FRAMEWORK_EXTENSIONS = {'DEFAULT_PARENT_LOOKUP_KWARG_NAME_PREFIX': ''}

    ACCOUNT_EMAIL_VERIFICATION = 'none'

    DANDI_ALLOW_LOCALHOST_URLS = False

    # Workaround for static file storage to work correctly on Django 4.
    # Taken from https://github.com/axnsan12/drf-yasg/issues/761#issuecomment-1031381674
    STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'

    @staticmethod
    def mutate_configuration(configuration: Type[ComposedConfiguration]):
        # Install local apps first, to ensure any overridden resources are found first
        configuration.INSTALLED_APPS = [
            'dandiapi.api.apps.PublishConfig',
        ] + configuration.INSTALLED_APPS

        # Install additional apps
        configuration.INSTALLED_APPS += [
            'guardian',
            'allauth.socialaccount.providers.github',
        ]

        # Authentication
        configuration.AUTHENTICATION_BACKENDS += [
            'guardian.backends.ObjectPermissionBackend'
        ]
        configuration.REST_FRAMEWORK['DEFAULT_AUTHENTICATION_CLASSES'] += [
            # TODO remove TokenAuthentication, it is only here to support
            # the setTokenHack login workaround
            'rest_framework.authentication.TokenAuthentication',
        ]

        # Permission
        configuration.REST_FRAMEWORK['DEFAULT_PERMISSION_CLASSES'] += [
            'dandiapi.api.permissions.IsApprovedOrReadOnly'
        ]

        # Pagination
        configuration.REST_FRAMEWORK[
            'DEFAULT_PAGINATION_CLASS'] = 'dandiapi.api.views.common.DandiPagination'

        # If this environment variable is set, the pydantic model will allow URLs with localhost
        # in them. This is important for development and testing environments, where URLs will
        # frequently point to localhost.
        if configuration.DANDI_ALLOW_LOCALHOST_URLS:
            os.environ['DANDI_ALLOW_LOCALHOST_URLS'] = 'True'

    DANDI_DANDISETS_BUCKET_NAME = values.Value(environ_required=True)
    DANDI_DANDISETS_BUCKET_PREFIX = values.Value(default='', environ=True)
    DANDI_DANDISETS_EMBARGO_BUCKET_NAME = values.Value(environ_required=True)
    DANDI_DANDISETS_EMBARGO_BUCKET_PREFIX = values.Value(default='',
                                                         environ=True)
    DANDI_ZARR_PREFIX_NAME = values.Value(default='zarr', environ=True)
    DANDI_ZARR_CHECKSUM_PREFIX_NAME = values.Value(default='zarr-checksums',
                                                   environ=True)

    # Mainly applies to unembargo
    DANDI_MULTIPART_COPY_MAX_WORKERS = values.IntegerValue(environ=True,
                                                           default=50)

    # This is where the schema version should be set.
    # It can optionally be overwritten with the environment variable, but that should only be
    # considered a temporary fix.
    DANDI_SCHEMA_VERSION = values.Value(default='0.6.2', environ=True)

    DANDI_DOI_API_URL = values.URLValue(environ=True)
    DANDI_DOI_API_USER = values.Value(environ=True)
    DANDI_DOI_API_PASSWORD = values.Value(environ=True)
    DANDI_DOI_API_PREFIX = values.Value(environ=True)
    DANDI_DOI_PUBLISH = values.BooleanValue(environ=True, default=False)
    DANDI_WEB_APP_URL = values.URLValue(environ_required=True)
    DANDI_API_URL = values.URLValue(environ_required=True)

    DANDI_VALIDATION_JOB_INTERVAL = values.IntegerValue(environ=True,
                                                        default=60)

    # The CloudAMQP connection was dying, using the heartbeat should keep it alive
    CELERY_BROKER_HEARTBEAT = 20

    # Clearing out the stock `SWAGGER_SETTINGS` variable causes a Django login
    # button to appear in Swagger, along with a spurious "authorize" button that
    # doesn't work. This at least enables us to authorize to the Swagger page on
    # the spot, which is quite useful.
    #
    # When Brian Helba is able to resolve this problem upstream (in
    # django-composed-configuration) we can remove this setting.
    SWAGGER_SETTINGS = {
        'DEFAULT_AUTO_SCHEMA_CLASS': 'dandiapi.swagger.DANDISwaggerAutoSchema',
    }

    # Some tasks working with lots of data need lots of memory, so we need to artificially lower
    # the number of concurrent tasks (default is 8) to keep memory usage down.
    CELERY_WORKER_CONCURRENCY = values.IntegerValue(environ=True, default=8)

    # Automatically approve new users by default
    AUTO_APPROVE_USERS = True
class Core(AWS, GCP, Celery, S3, GCS, Configuration):
    """Settings that will never change per-environment."""

    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    THIS_DIR = os.path.dirname(os.path.abspath(__file__))
    BASE_DIR = os.path.dirname(THIS_DIR)

    VERSION = get_version(BASE_DIR)

    # Using the default first site found by django.contrib.sites
    SITE_ID = 1

    INSTALLED_APPS = [
        # Django apps
        "django.contrib.sites",
        "django.contrib.auth",
        "django.contrib.contenttypes",
        "django.contrib.sessions",
        # Project specific apps
        "tecken.apps.TeckenAppConfig",
        "tecken.symbolicate",
        "tecken.download",
        "tecken.upload",
        "tecken.tokens",
        "tecken.api",
        "tecken.useradmin",
        "tecken.benchmarking",
        # Third party apps
        "dockerflow.django",
        # Third party apps, that need to be listed last
        "mozilla_django_oidc",
    ]

    # June 2017: Notice that we're NOT adding
    # 'mozilla_django_oidc.middleware.RefreshIDToken'. That's because
    # most views in this project are expected to be called as AJAX
    # or from curl. So it doesn't make sense to require every request
    # to refresh the ID token.
    # Once there is a way to do OIDC ID token refreshing without needing
    # the client to redirect, we can enable that.
    # Note also, the ostensible reason for using 'RefreshIDToken' is
    # to check that a once-authenticated user is still a valid user.
    # So if that's "disabled", that's why we have rather short session
    # cookie age.
    MIDDLEWARE = (
        "dockerflow.django.middleware.DockerflowMiddleware",
        # 'django.middleware.csrf.CsrfViewMiddleware',
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.middleware.common.CommonMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "tecken.tokens.middleware.APITokenAuthenticationMiddleware",
        # Important that this comes after APITokenAuthenticationMiddleware
        "tecken.useradmin.middleware.NotBlockedInAuth0Middleware",
        "whitenoise.middleware.WhiteNoiseMiddleware",
    )

    ROOT_URLCONF = "tecken.urls"

    WSGI_APPLICATION = "tecken.wsgi.application"

    # Add the django-allauth authentication backend.
    AUTHENTICATION_BACKENDS = (
        "django.contrib.auth.backends.ModelBackend",
        "mozilla_django_oidc.auth.OIDCAuthenticationBackend",
    )

    # Internationalization
    # https://docs.djangoproject.com/en/1.9/topics/i18n/
    LANGUAGE_CODE = "en-us"
    TIME_ZONE = "UTC"
    USE_I18N = False
    USE_L10N = False
    USE_TZ = True
    DATETIME_FORMAT = "Y-m-d H:i"  # simplified ISO format since we assume UTC

    STATIC_ROOT = values.Value(
        default=os.path.join(BASE_DIR, "frontend/build"))

    STATIC_URL = "/"

    # The default Cache-Control max-age used,
    WHITENOISE_MAX_AGE = values.IntegerValue(60 * 60)

    SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
    SESSION_CACHE_ALIAS = "default"

    # System Checks
    # Override certain builtin Django system checks because we know
    # with confidence we do these good deeds in Nginx.
    # https://docs.djangoproject.com/en/1.11/ref/checks/#security
    SILENCED_SYSTEM_CHECKS = [
        "security.W001",  # Dealt with using Nginx headers
        "security.W002",  # Dealt with using Nginx headers
        "security.W003",  # CSRF is explicit only on the views that need it
        # We can't set SECURE_HSTS_INCLUDE_SUBDOMAINS since this runs under a
        # mozilla.org subdomain
        "security.W005",
        "security.W004",  # Strict-Transport-Security is set in Nginx
    ]

    OIDC_RP_CLIENT_ID = values.SecretValue()
    OIDC_RP_CLIENT_SECRET = values.SecretValue()

    OIDC_OP_AUTHORIZATION_ENDPOINT = values.URLValue(
        "https://auth.mozilla.auth0.com/authorize")
    OIDC_OP_TOKEN_ENDPOINT = values.URLValue(
        "https://auth.mozilla.auth0.com/oauth/token")
    OIDC_OP_USER_ENDPOINT = values.URLValue(
        "https://auth.mozilla.auth0.com/userinfo")

    # Feature flag for the Auth0 Management API check that checks if users
    # are still valid and not blocked in Auth0's user database.
    ENABLE_AUTH0_BLOCKED_CHECK = values.BooleanValue(True)

    # There's a middleware that checks if the user is NOT blocked in
    # Auth0. But we don't want to do it for every single request, since
    # it's slowish, so we throttle that check with a cache interval.
    NOT_BLOCKED_IN_AUTH0_INTERVAL_SECONDS = values.IntegerValue(60 * 60 * 24)

    # Keep it quite short because we don't have a practical way to do
    # OIDC ID token renewal for this AJAX and curl heavy app.
    SESSION_COOKIE_AGE = values.IntegerValue(60 * 60 * 24 * 365)

    # Where users get redirected after successfully signing in
    LOGIN_REDIRECT_URL = "/?signedin=true"
    LOGIN_REDIRECT_URL_FAILURE = "/?signin=failed"

    # API Token authentication is off by default until Tecken has
    # gone through a security checklist.
    ENABLE_TOKENS_AUTHENTICATION = values.BooleanValue(True)

    TOKENS_DEFAULT_EXPIRATION_DAYS = values.IntegerValue(365)  # 1 year

    # Feature flag for enabling or disabling the possible downloading
    # of missing symbols from Microsoft.
    ENABLE_DOWNLOAD_FROM_MICROSOFT = values.BooleanValue(False)

    # When a symbol is tried to be downloaded, and it turns out the symbol
    # does *not* exist in S3, we write this down so all missing symbols
    # can be post-processed after.
    # But we only need to write it down once per symbol. There's a memoizing
    # guard and this defines how long it should cache that it memoized.
    MEMOIZE_LOG_MISSING_SYMBOLS_SECONDS = values.IntegerValue(60 * 60 * 24)

    # Whether or not benchmarking is enabled. It's only useful to have this
    # enabled in environments dedicated for testing and load testing.
    BENCHMARKING_ENABLED = values.BooleanValue(False)

    # When we ask S3 for the size (if it exists) of a symbol already in S3
    # this can be cached. This value determines how long we do that caching.
    MEMOIZE_KEY_EXISTING_SIZE_SECONDS = values.IntegerValue(60 * 60 * 24)

    # When we upload a .zip file, we iterate over the content and for each
    # file within (that isn't immediately "ignorable") we kick off a
    # function which figures out what (and how) to process the file.
    # That function involves doing a S3/GCS GET (technically ListObjectsV2),
    # (possible) gzipping the payload and (possibly) a S3/GCS PUT.
    # All of these function calls get put in a
    # concurrent.futures.ThreadPoolExecutor pool. This setting is about
    # how many of these to start, max.
    UPLOAD_FILE_UPLOAD_MAX_WORKERS = values.IntegerValue(default=None)

    # Whether to store the missing symbols in Postgres or not.
    # If you disable this, at the time of writing, missing symbols
    # will be stored in the Redis default cache.
    ENABLE_STORE_MISSING_SYMBOLS = values.BooleanValue(True)

    # The prefix used when generating directories in the temp directory.
    UPLOAD_TEMPDIR_PREFIX = values.Value("raw-uploads")

    # When doing local development, especially load testing, it's sometimes
    # useful to be able to bypass all URL checks for Upload by Download.
    ALLOW_UPLOAD_BY_ANY_DOMAIN = values.BooleanValue(False)

    # This is only really meant for the sake of being overrideable by
    # other setting classes; in particular the 'Test' class.
    SYNCHRONOUS_UPLOAD_FILE_UPLOAD = False

    DOWNLOAD_LEGACY_PRODUCTS_PREFIXES = [
        "firefox",
        "seamonkey",
        "sunbird",
        "thunderbird",
        "xulrunner",
        "fennec",
        "b2g",
    ]
Exemplo n.º 18
0
class Base(Core):
    """Configuration that may change per-environment, some with defaults."""

    SECRET_KEY = values.SecretValue()

    DEBUG = values.BooleanValue(default=False)

    ALLOWED_HOSTS = values.ListValue([])

    #: The URL under which this instance is running
    SITE_URL = values.URLValue('http://*****:*****@db/postgres')

    REDIS_URL_DEFAULT = 'redis://redis:6379/1'
    CACHES = values.CacheURLValue(
        REDIS_URL_DEFAULT,
        environ_prefix=None,
        environ_name='REDIS_URL',
    )
    # Use redis as the Celery broker.
    CELERY_BROKER_URL = os.environ.get('REDIS_URL', REDIS_URL_DEFAULT)

    LOGGING_USE_JSON = values.BooleanValue(False)

    def LOGGING(self):
        return {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'json': {
                    '()': 'dockerflow.logging.JsonLogFormatter',
                    'logger_name': 'atmo',
                },
                'verbose': {
                    'format': '%(levelname)s %(asctime)s %(name)s %(message)s',
                },
                'django.server': {
                    '()': 'django.utils.log.ServerFormatter',
                    'format': '[%(server_time)s] %(message)s',
                },
            },
            'handlers': {
                'console': {
                    'level': 'DEBUG',
                    'class': 'logging.StreamHandler',
                    'formatter': 'json' if self.LOGGING_USE_JSON else 'verbose',
                },
                'sentry': {
                    'level': 'ERROR',
                    'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
                },
                'django.server': {
                    'level': 'INFO',
                    'class': 'logging.StreamHandler',
                    'formatter': 'django.server',
                },
            },
            'loggers': {
                'root': {
                    'level': 'INFO',
                    'handlers': ['sentry', 'console'],
                },
                'django.db.backends': {
                    'level': 'ERROR',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'django.server': {
                    'handlers': ['django.server'],
                    'level': 'INFO',
                    'propagate': False,
                },
                'raven': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'sentry.errors': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'atmo': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'celery.task': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'redbeat.schedulers': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'request.summary': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
            },
        }
Exemplo n.º 19
0
class Base(Core, CORS, OIDC, Metrics):
    """Settings that may change per-environment, some with defaults."""

    # Flags that affect other settings, via setting methods below
    LOGGING_USE_JSON = values.BooleanValue(False)
    USE_OIDC = values.BooleanValue(False)

    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])
    SILENCED_SYSTEM_CHECKS = values.ListValue([
        # We've subclassed Django's security middleware, so Django's
        # checks can't tell we are using the middleware.
        "security.W001",
        # We have disabled CSRF as we do not use cookie-based authentication.
        # As a result the CSRF middleware check is not required.
        "security.W003",
    ])

    # Authentication
    def AUTHENTICATION_BACKENDS(self):
        if self.USE_OIDC:
            return ["normandy.base.auth_backends.EmailOnlyRemoteUserBackend"]
        else:
            return ["normandy.base.auth_backends.LoggingModelBackend"]

    OIDC_REMOTE_AUTH_HEADER = values.Value("HTTP_REMOTE_USER")

    # Middleware that _most_ environments will need. Subclasses can override this list.
    EXTRA_MIDDLEWARE = [
        "django.contrib.sessions.middleware.SessionMiddleware",
        "django.contrib.auth.middleware.AuthenticationMiddleware",
        "django.contrib.messages.middleware.MessageMiddleware",
    ]

    def MIDDLEWARE(self):
        """
        Determine middleware by combining the core set and
        per-environment set.
        """
        middleware = Core.MIDDLEWARE + self.EXTRA_MIDDLEWARE
        if self.USE_OIDC:
            middleware.append(
                "normandy.base.middleware.ConfigurableRemoteUserMiddleware")
        return middleware

    def LOGGING(self):
        return {
            "version": 1,
            "disable_existing_loggers": False,
            "formatters": {
                "json": {
                    "()": "dockerflow.logging.JsonLogFormatter",
                    "logger_name": "normandy"
                },
                "development": {
                    "format": "%(levelname)s %(asctime)s %(name)s %(message)s"
                },
            },
            "handlers": {
                "console": {
                    "level":
                    "DEBUG",
                    "class":
                    "logging.StreamHandler",
                    "formatter":
                    "json" if self.LOGGING_USE_JSON else "development",
                }
            },
            "root": {
                "handlers": ["console"],
                "level": "WARNING"
            },
            "loggers": {
                "normandy": {
                    "propagate": False,
                    "handlers": ["console"],
                    "level": "DEBUG"
                },
                "request.summary": {
                    "propagate": False,
                    "handlers": ["console"],
                    "level": "DEBUG"
                },
            },
        }

    # Remote services
    DATABASES = values.DatabaseURLValue(
        "postgres://postgres@localhost/normandy")
    CONN_MAX_AGE = values.IntegerValue(0)
    GEOIP2_DATABASE = values.Value(
        os.path.join(Core.BASE_DIR, "GeoLite2-Country.mmdb"))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value("django.core.mail.backends.smtp.EmailBackend")

    def RAVEN_CONFIG(self):
        version_path = os.path.join(Core.BASE_DIR, "version.json")
        try:
            with open(version_path) as f:
                build_info = json.loads(f.read())
                version = build_info.get("version")
        except IOError:
            version = None

        return {
            "dsn": values.URLValue(None, environ_name="RAVEN_CONFIG_DSN"),
            "release": values.Value(version,
                                    environ_name="RAVEN_CONFIG_RELEASE"),
        }

    # statsd
    STATSD_HOST = values.Value("localhost")
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value("normandy")
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    AUTH_PASSWORD_VALIDATORS = [
        {
            "NAME":
            "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
        },
        {
            "NAME":
            "django.contrib.auth.password_validation.MinimumLengthValidator"
        },
        {
            "NAME":
            "django.contrib.auth.password_validation.CommonPasswordValidator"
        },
        {
            "NAME":
            "django.contrib.auth.password_validation.NumericPasswordValidator"
        },
    ]
    PASSWORD_HASHERS = values.ListValue([
        "django.contrib.auth.hashers.BCryptSHA256PasswordHasher",
        "django.contrib.auth.hashers.PBKDF2PasswordHasher",
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(True)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value("DENY")
    REQUIRE_RECIPE_AUTH = values.BooleanValue(True)

    # Media and static settings
    STATIC_URL = values.Value("/static/")
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, "static"))
    MEDIA_URL = values.Value("/media/")
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, "media"))

    STATICFILES_DIRS = (os.path.join(Core.BASE_DIR, "assets"), )

    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)
    # URL that bypasses any CDNs
    APP_SERVER_URL = values.URLValue(None)

    # URL for the CSP report-uri directive.
    CSP_REPORT_URI = values.Value("/__cspreport__")

    # Normandy settings
    ADMIN_ENABLED = values.BooleanValue(True)
    IMMUTABLE_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)
    NUM_PROXIES = values.IntegerValue(0)
    API_CACHE_TIME = values.IntegerValue(30)
    API_CACHE_ENABLED = values.BooleanValue(True)
    PERMANENT_REDIRECT_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 30)
    HTTPS_REDIRECT_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 30)

    # If true, approvals must come from two separate users. If false, the same
    # user can approve their own request.
    PEER_APPROVAL_ENFORCED = values.BooleanValue(True)

    # Autograph settings
    AUTOGRAPH_URL = values.Value()
    AUTOGRAPH_HAWK_ID = values.Value()
    AUTOGRAPH_HAWK_SECRET_KEY = values.Value()
    AUTOGRAPH_SIGNATURE_MAX_AGE = values.IntegerValue(60 * 60 * 24 * 7)
    AUTOGRAPH_X5U_CACHE_BUST = values.Value(None)

    # Remote Settings connection configuration
    REMOTE_SETTINGS_URL = values.Value()
    REMOTE_SETTINGS_USERNAME = values.Value()
    REMOTE_SETTINGS_PASSWORD = values.Value()
    REMOTE_SETTINGS_BUCKET_ID = values.Value("main-workspace")
    REMOTE_SETTINGS_COLLECTION_ID = values.Value("normandy-recipes")
    REMOTE_SETTINGS_RETRY_REQUESTS = values.IntegerValue(3)

    # How many days before expiration to warn for expired certificates
    CERTIFICATES_EXPIRE_EARLY_DAYS = values.IntegerValue(None)
    CERTIFICATES_CHECK_VALIDITY = values.BooleanValue(True)
    CERTIFICATES_EXPECTED_ROOT_HASH = values.Value(None)
    CERTIFICATES_EXPECTED_SUBJECT_CN = values.Value(
        "normandy.content-signature.mozilla.org")

    # Storage settings
    DEFAULT_FILE_STORAGE = values.Value(
        "normandy.base.storage.NormandyS3Boto3Storage")

    PROD_DETAILS_DIR = values.Value(
        os.path.join(Core.BASE_DIR, "product_details"))

    # AWS settings
    AWS_ACCESS_KEY_ID = values.Value()
    AWS_SECRET_ACCESS_KEY = values.Value()
    AWS_STORAGE_BUCKET_NAME = values.Value()
    GS_BUCKET_NAME = values.Value()
    GS_DEFAULT_ACL = values.Value("publicRead")

    GITHUB_URL = values.Value("https://github.com/mozilla/normandy")
Exemplo n.º 20
0
class Base(Configuration):
    '''
    All configurations should sublcass this base class.
    
    This contains all that is required, aside from custom endpoints that will
    vary per deployment and/or environment.

    Defaults have been set to err on the side of caution, so DEBUG, ADMIN, etc 
    will have to be explictly turned on where necessary.
    '''

    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

    # THIS IS JUST A DEFAULT THAT WAS GENERATED FOR LOCAL DEVELOPMENT

    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = values.Value('abceasyas123')

    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = values.BooleanValue(False)
    ADMIN_ENABLED = values.BooleanValue(False)

    SESSION_EXPIRE_AT_BROWSER_CLOSE = values.BooleanValue(True)

    AUTH_USER_MODEL = values.Value('users.User')

    MEMBERSHIP_ENCODE_KEY = values.Value('')
    MEMBERSHIP_RENEWAL_URL_BASE = values.URLValue('')

    SHARED_SESSION_SITES = values.ListValue([])
    SESSION_COOKIE_DOMAIN = values.Value()
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

    ALLOWED_HOSTS = values.ListValue([])
    SITE_ID = values.IntegerValue(1)

    ADMINS = [('Sir Terence', '*****@*****.**')]

    SERVER_EMAIL = '*****@*****.**'

    # SESSION_COOKIE_AGE = 60*60*24

    X_FRAME_OPTIONS = 'ALLOW'

    INSTALLED_APPS = values.ListValue([
        # Django packages
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'django.contrib.sites',
        'django.contrib.sitemaps',

        # External packages
        'captcha',
        'debug_toolbar',
        'django_jinja',
        'raven.contrib.django.raven_compat',
        'rest_framework_swagger',
        'rest_framework.authtoken',
        'rest_framework',
        'rosetta',
        'shared_session',
        'storages',
        'webpack_loader',
        'cacheops',
        'robots',
        'import_export',

        # Application packages
        'clublink.base',
        'clublink.certificates',
        'clublink.clubs',
        'clublink.cms',
        'clublink.corp',
        'clublink.landings',
        'clublink.users',
        'clublink.emails',
    ])

    MIDDLEWARE = values.ListValue([
        'debug_toolbar.middleware.DebugToolbarMiddleware',

        # Custom middleware
        'clublink.base.middleware.HostnameRoutingMiddleware',
        'clublink.base.middleware.ShortCircuitMiddleware',

        # Django middleware
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',

        # Sites middleware
        'django.contrib.sites.middleware.CurrentSiteMiddleware',

        # Custom middleware
        'clublink.base.middleware.SpoofedUserMiddleware',
        'clublink.base.middleware.ScaffoldingMiddleware',
        'clublink.base.middleware.LocaleMiddleware'
    ])

    ROOT_URLCONF = values.Value('clublink.urls.common')

    TEMPLATES = values.ListValue([
        {
            'BACKEND': 'django_jinja.backend.Jinja2',
            'DIRS': [
                'templates',
            ],
            'APP_DIRS': True,
            'OPTIONS': {
                'match_regex':
                '.+(\.jinja|\.txt)',
                'match_extension':
                None,
                'extensions':
                DEFAULT_EXTENSIONS + [
                    'webpack_loader.contrib.jinja2ext.WebpackExtension',
                    'jinja2.ext.i18n',
                    'cacheops.jinja2.cache',
                    'clublink.base.extensions.SharedSession',
                ],
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.i18n',
                    'django.template.context_processors.media',
                    'django.template.context_processors.static',
                    'django.template.context_processors.tz',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                    # Custom context processors
                    'clublink.base.context_processors.globals'
                ],
            }
        },
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        }
    ])

    WSGI_APPLICATION = values.Value('clublink.wsgi.application')

    CACHES = {
        'default': {
            'BACKEND':
            'django_redis.cache.RedisCache',
            'LOCATION':
            values.Value('redis://127.0.0.1:6379/1',
                         environ_name='CACHES_DEFAULT_LOCATION'),
            'OPTIONS': {
                'CLIENT_CLASS': 'django_redis.client.DefaultClient',
            }
        }
    }

    # Database
    # https://docs.djangoproject.com/en/1.11/ref/settings/#

    # As per: https://github.com/kennethreitz/dj-database-url#url-schema
    ### <-----------------------------------------------------------------> ###
    ### NOTE!!!! THIS IS THE ONE VALUE THAT IS NOT PREFIXED WITH DJANGO_ ###
    # DATABASE_DICT = values.DictValue()

    # LEGACY_DATABASE_DICT = values.DictValue()
    ### <-----------------------------------------------------------------> ###

    DATABASE_ENGINE = values.Value("django.db.backends.mysql")
    DATABASE_NAME = values.Value()
    DATABASE_USER = values.Value()
    DATABASE_PASSWORD = values.Value()
    DATABASE_HOST = values.Value()
    DATABASE_PORT = values.Value('3306')

    LEGACY_DATABASE_ENGINE = values.Value("django.db.backends.mysql")
    LEGACY_DATABASE_NAME = values.Value()
    LEGACY_DATABASE_USER = values.Value()
    LEGACY_DATABASE_PASSWORD = values.Value()
    LEGACY_DATABASE_HOST = values.Value()
    LEGACY_DATABASE_PORT = values.Value('3306')

    @property
    def DATABASES(self):
        DATABASES = {
            'default': {
                'ENGINE': self.DATABASE_ENGINE,
                'NAME': self.DATABASE_NAME,
                'USER': self.DATABASE_USER,
                'PASSWORD': self.DATABASE_PASSWORD,
                'HOST': self.DATABASE_HOST,
                'PORT': self.DATABASE_PORT
            }
        }
        return DATABASES

    # Password validation
    # https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

    AUTH_PASSWORD_VALIDATORS = values.ListValue([
        {
            'NAME':
            'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ])

    # Internationalization
    # https://docs.djangoproject.com/en/1.11/topics/i18n/

    LANGUAGE_CODE = values.Value('en')
    LANGUAGES = values.SingleNestedTupleValue((
        ('en', _('English')),
        ('fr', _('French')),
    ))
    LOCALE_PATHS = values.SingleNestedTupleValue(
        (os.path.join(BASE_DIR, 'locale'), ))

    TIME_ZONE = values.Value('America/Toronto')

    USE_I18N = values.BooleanValue(True)

    USE_L10N = values.BooleanValue(True)

    USE_TZ = values.BooleanValue(True)

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.11/howto/static-files/
    DEFAULT_FILE_STORAGE = values.Value(
        'django.contrib.staticfiles.storage.StaticFilesStorage')
    STATICFILES_DIRS = (os.path.join(BASE_DIR, 'assets'), )

    # STATIC #
    STATIC_URL = values.Value('/static/')
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    STATICFILES_LOCATION = values.Value('static')
    STATICFILES_STORAGE = values.Value(
        'django.contrib.staticfiles.storage.StaticFilesStorage')

    # ASSETS #
    ASSETS_URL = values.Value('/asset_files/')
    ASSETS_ROOT = os.path.join(BASE_DIR, 'asset_files')
    ASSETS_LOCATION = values.Value('assets')
    ASSETS_FILE_STORAGE = values.Value(
        'django.contrib.staticfiles.storage.StaticFilesStorage')

    # MEDIA #
    MEDIA_URL = values.Value('/media/')
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
    MEDIA_LOCATION = values.Value('media')

    # WEBPACK #
    WEBPACK_LOADER = values.DictValue({
        'DEFAULT': {
            'BUNDLE_DIR_NAME': 'bundles/',
            'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json')
        },
    })

    SWAGGER_SETTINGS = values.DictValue({
        'DOC_EXPANSION': 'list',
        'JSON_EDITOR': True,
    })

    CSRF_COOKIE_HTTPONLY = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([r'^__health__/$'])

    GIFT_CERTIFICATE_SITE_URL = values.URLValue()
    CORP_SITE_URL = values.URLValue()
    CLUB_SITE_URL = values.Value()
    ADMIN_SITE_URL = values.URLValue()

    ADMIN_HOSTNAME = values.RegexValue(r'^admin\.')
    CORP_HOSTNAME = values.RegexValue(r'^(www\.)?')
    API_HOSTNAME = values.RegexValue(r'^api\.')
    GIFT_CERTIFICATE_HOSTNAME = values.RegexValue(r'^giftcertificates\.')
    GIFT_CARDS_HOSTNAME = values.RegexValue(r'^giftcards\.')

    def HOSTNAME_URLCONFS(self):
        return (
            (self.ADMIN_HOSTNAME, 'clublink.urls.admin'),
            (self.CORP_HOSTNAME, 'clublink.urls.corp'),
            (self.API_HOSTNAME, 'clublink.urls.api'),
            (self.GIFT_CERTIFICATE_HOSTNAME, 'clublink.urls.gc'),
            (self.GIFT_CARDS_HOSTNAME, 'clublink.urls.gift_cards'),
        )

    def HOSTNAME_LANGUAGES(self):
        return (
            (self.ADMIN_HOSTNAME, ('en', )),
            (self.GIFT_CERTIFICATE_HOSTNAME, ('en', )),
        )

    VPN_PROTECTED_VIEWS_ENABLED = values.BooleanValue(True)
    VPN_IP_ADDRESS = values.Value('10.8.0.1')

    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_USE_TLS = values.BooleanValue(True)

    DEFAULT_FROM_EMAIL_ADDRESS = values.EmailValue('*****@*****.**')
    MEMBER_SERVICES_EMAIL_ADDRESS = values.EmailValue(
        '*****@*****.**')
    GIFT_CERTIFICATE_EMAIL_ADDRESS = values.EmailValue(
        '*****@*****.**')
    CORPORATE_EVENTS_EMAIL_ADDRESS = values.EmailValue(
        '*****@*****.**')
    MEMBERSHIP_SALES_EMAIL_ADDRESS = values.EmailValue(
        '*****@*****.**')
    EVENTS_EMAIL_ADDRESSES = values.ListValue([
        '*****@*****.**',
        '*****@*****.**',
        '*****@*****.**',
    ])

    IBS_API_WSDL = values.Value()
    IBS_API_USER = values.Value()
    IBS_API_PASSWORD = values.Value()

    IBS_WEBRES_API_ROOT = values.Value()
    IBS_WEBRES_API_USER = values.Value()
    IBS_WEBRES_API_PASSWORD = values.Value()

    GOOGLE_MAPS_API_KEY = values.Value()
    GOOGLE_ANALYTICS_TRACKING_ID = values.Value()

    DEFAULT_CERTIFICATE_EMPLOYEE_NUMBER = values.Value()
    DEFAULT_CERTIFICATE_MEMBERSHIP_NUMBER = values.Value('')
    CERTIFICATES_BATCH_LIMIT = values.IntegerValue(150)

    DATA_UPLOAD_MAX_NUMBER_FIELDS = values.IntegerValue(1000)

    GIFT_CERTIFICATE_IP_WHITELIST_ENABLED = values.BooleanValue(False)
    GIFT_CERTIFICATE_IP_WHITELIST = values.ListValue()

    AES_SHARED_KEY = values.Value()

    DYNAMICS_HOST = values.Value()
    DYNAMICS_USER = values.Value()
    DYNAMICS_PASSWORD = values.Value()
    DYNAMICS_DATABASE = values.Value()

    NOCAPTCHA = values.BooleanValue(True)
    RECAPTCHA_PUBLIC_KEY = values.Value()
    RECAPTCHA_PRIVATE_KEY = values.Value()

    PASSWORD_RESET_DEBUG = values.BooleanValue(True)
    PASSWORD_RESET_DEBUG_EMAIL_ADDRESSES = values.ListValue()

    ASSETS_FILE_STORAGE = values.Value(
        'django.core.files.storage.FileSystemStorage')

    SEARCH_ENGINE_INDEXING_DISABLED = values.BooleanValue(False)

    SESSION_EXPIRE_AT_BROWSER_CLOSE = values.BooleanValue(True)

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
            'rest_framework.authentication.SessionAuthentication',
        ),
        'DEFAULT_PERMISSION_CLASSES':
        ('rest_framework.permissions.IsAuthenticated', ),
        'DEFAULT_RENDERER_CLASSES':
        ('rest_framework.renderers.JSONRenderer', ),
        'DEFAULT_PAGINATION_CLASS':
        'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE':
        50,
        'EXCEPTION_HANDLER':
        'clublink.base.api.handlers.logging_exception_handler',
    }

    CELERY_BROKER_URL = values.Value()
    CELERY_RESULT_BACKEND = values.Value()
Exemplo n.º 21
0
class Common(Configuration):
    REPO_ROOT_DIR: str = environ.Path(__file__) - 2
    APPS_ROOT_DIR: str = REPO_ROOT_DIR.path('aperte')

    env = environ.Env()

    # See https://docs.djangoproject.com/en/2.0/ref/settings/ for a description
    # of each Django setting.

    # CORE SETTINGS
    # --------------------------------------------------------------------------
    DEBUG = values.BooleanValue(False)
    TIME_ZONE = values.Value('UTC')
    USE_TZ = True
    if USE_TZ:
        from django.conf.locale.en import formats
        formats.DATETIME_FORMAT = values.Value(
            'm/d/Y h:i:s T', environ_name='DJANGO_DATETIME_FORMAT')
    LANGUAGE_CODE = values.Value('en-us')
    LANGUAGES = (('en', _('English')), )
    LOCALE_PATHS = (str(APPS_ROOT_DIR.path('locale')), )
    USE_I18N = values.BooleanValue(True)
    USE_L10N = values.BooleanValue(True)
    FIXTURE_DIRS = (str(APPS_ROOT_DIR.path('fixtures')), )
    WSGI_APPLICATION = 'wsgi.application'
    # Note: This variable is an empty list by default for security reasons. The
    #       allowed hosts for Django to serve must be specified explicitly in
    #       all environments.
    ALLOWED_HOSTS = values.ListValue([], environ_required=True)

    # INSTALLED APPS SETTINGS
    # --------------------------------------------------------------------------
    DJANGO_APPS = [
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django_sites',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'django.contrib.admin',
    ]
    LOCAL_APPS = [
        'aperte.base',
        'aperte.users',
    ]
    THIRD_PARTY_APPS = [
        # TODO: Re-enable this.
        # 'allauth',
        # 'allauth.account',
        # 'allauth.socialaccount',
        # 'allauth.socialaccount.providers.github',
        # 'allauth.socialaccount.providers.google',
        # 'allauth.socialaccount.providers.linkedin',
        # 'allauth.socialaccount.providers.linkedin_oauth2',
        'versatileimagefield',
        # TODO: Re-enable this.
        # 'corsheaders',
        'raven.contrib.django.raven_compat',
        'mail_templated',
    ]
    INSTALLED_APPS = DJANGO_APPS + LOCAL_APPS + THIRD_PARTY_APPS

    # URL SETTINGS
    # --------------------------------------------------------------------------
    ROOT_URLCONF = 'aperte.urls'

    # ADMIN SETTINGS
    # --------------------------------------------------------------------------
    ADMIN_URL = values.Value('admin')
    ADMINS = [
        ("""Adam Cook""", '*****@*****.**'),
    ]
    ADMINS = values.SingleNestedTupleValue(
        (('SME Virtual Network Admin', '*****@*****.**')))
    MANAGERS = ADMINS

    # AUTHENTICATION AND LOGIN SETTINGS
    # --------------------------------------------------------------------------
    AUTH_USER_MODEL = 'users.User'
    AUTHENTICATION_BACKENDS = [
        'django.contrib.auth.backends.ModelBackend',
        # TODO: Re-enable this.
        #'allauth.account.auth_backends.AuthenticationBackend',
    ]
    PASSWORD_HASHERS = [
        'django.contrib.auth.hashers.Argon2PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.BCryptPasswordHasher',
    ]
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME':
            'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.MinimumLengthValidator',
            'OPTIONS': {
                'min_length': 6,
            }
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]
    LOGIN_REDIRECT_URL = 'users:redirect'
    LOGIN_URL = 'login'

    # EMAIL SETTINGS
    # --------------------------------------------------------------------------
    DEFAULT_FROM_EMAIL = values.Value(
        'SME Virtual Network <*****@*****.**>')
    EMAIL_SUBJECT_PREFIX = values.Value('[SME Virtual Network]')
    EMAIL_USE_TLS = values.BooleanValue(True)
    SERVER_EMAIL = values.Value(DEFAULT_FROM_EMAIL)

    # DATABASE SETTINGS
    # --------------------------------------------------------------------------
    DATABASES = {
        'default': {
            'ENGINE':
            'django.db.backends.postgresql',
            'NAME':
            values.Value('',
                         environ_name='DATABASE_NAME_DEFAULT',
                         environ_required=True),
            'USER':
            values.Value('',
                         environ_name='DATABASE_USER_DEFAULT',
                         environ_required=True),
            'PASSWORD':
            values.SecretValue(environ_name='DATABASE_PASSWORD_DEFAULT'),
            'HOST':
            values.Value('',
                         environ_name='DATABASE_HOST_DEFAULT',
                         environ_required=True),
            'PORT':
            values.Value('5432', environ_name='DATABASE_PORT_DEFAULT'),
            'ATOMIC_REQUESTS':
            True,
            'CONN_MAX_AGE':
            10
        }
    }

    # TEMPLATE SETTINGS
    # --------------------------------------------------------------------------
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [
                str(APPS_ROOT_DIR.path('templates')),
            ],
            'OPTIONS': {
                'debug':
                DEBUG,
                'loaders': [
                    'django.template.loaders.filesystem.Loader',
                    'django.template.loaders.app_directories.Loader',
                ],
                'context_processors': [
                    'aperte.base.context_processors.site_settings',
                    'django.contrib.auth.context_processors.auth',
                    'django.template.context_processors.debug',
                    'django.template.context_processors.i18n',
                    'django.template.context_processors.media',
                    'django.template.context_processors.static',
                    'django.template.context_processors.tz',
                    'django.contrib.messages.context_processors.messages',
                    'django.template.context_processors.request',
                ],
            },
        },
    ]
    CSRF_FAILURE_VIEW = 'aperte.base.views.render_csrf_failure'

    # STATIC FILE SETTINGS
    # --------------------------------------------------------------------------
    # STATIC_ROOT - The absolute path to the directory where `collectstatic`
    # will collect static files for deployment. This is only used during
    # production (not development).
    STATIC_ROOT = str(REPO_ROOT_DIR.path('static'))
    # STATICFILES_DIRS - This setting defines the additional locations the
    # 'staticfiles' app will traverse if the 'FileSystemFinder' finder is
    # enabled.
    STATICFILES_DIRS = (str(APPS_ROOT_DIR.path('dist')), )
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    )

    if env.bool('DJANGO_DISABLE_WHITENOISE', default=False):
        # Whitenoise is disabled.
        # This branch is for a local development where `collectstatic` will not
        # be called any time the styles or scripts are changed. This makes
        # development faster as the browser can refresh with the latest builds
        # of the styles and/or scripts without having to call `collectstatic`
        # first.
        STATIC_URL = '/static/'
    else:
        # Whitenoise is enabled.
        # This branch is for a local development environment which enables
        # Whitenoise to test a staging or production environment before pushing
        # the code to the cloud.
        INSTALLED_APPS = INSTALLED_APPS + [
            'whitenoise.runserver_nostatic',
        ]
        STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
        STATIC_HOST = values.URLValue('',
                                      environ_name='STATIC_HOST',
                                      environ_required=True)
        STATIC_URL = str(STATIC_HOST) + '/static/'

    # django-sites SETTINGS
    # --------------------------------------------------------------------------
    # Note: Default setting is 'https' for security reasons. For development,
    #       the setting will likely have to be 'http'.
    SITE_SCHEME = values.Value('https')
    SITE_DOMAIN = values.Value('',
                               environ_name='SITE_DOMAIN',
                               environ_required=True)
    SITE_NAME = values.Value('SME Virtual Network')
    SITES = {
        'current': {
            'domain': SITE_DOMAIN,
            'scheme': SITE_SCHEME,
            'name': SITE_NAME
        },
    }
    SITE_ID = 'current'

    # MEDIA SETTINGS
    # --------------------------------------------------------------------------
    MEDIA_ROOT = str(REPO_ROOT_DIR.path('.media'))
    MEDIA_URL = values.Value('{}://{}/media/'.format(SITE_SCHEME, SITE_DOMAIN))

    # SECURITY SETTINGS
    # --------------------------------------------------------------------------
    SECRET_KEY = values.SecretValue()
    CSRF_COOKIE_HTTPONLY = False
    SESSION_COOKIE_HTTPONLY = True
    SECURE_CONTENT_TYPE_NOSNIFF = True
    SECURE_BROWSER_XSS_FILTER = True
    X_FRAME_OPTIONS = 'DENY'

    # django-log-request-id SETTINGS
    # --------------------------------------------------------------------------
    REQUEST_ID_RESPONSE_HEADER = 'REQUEST_ID'

    # LOGGING SETTINGS
    # --------------------------------------------------------------------------
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'filters': {
            'require_debug_false': {
                '()': 'django.utils.log.RequireDebugFalse'
            },
            'request_id': {
                '()': 'log_request_id.filters.RequestIDFilter'
            }
        },
        'formatters': {
            'complete': {
                'format':
                '%(asctime)s:[%(levelname)s]:logger=%(name)s:request_id=%(request_id)s message="%(message)s"'
            },
            'simple': {
                'format': '%(levelname)s:%(asctime)s: %(message)s'
            },
            'null': {
                'format': '%(message)s',
            },
        },
        'handlers': {
            'null': {
                'level': 'DEBUG',
                'class': 'logging.NullHandler',
            },
            'console': {
                'level': 'DEBUG',
                'class': 'logging.StreamHandler',
                'formatter': 'complete',
                'filters': ['request_id'],
            },
            'mail_admins': {
                'level': 'ERROR',
                'filters': ['require_debug_false'],
                'class': 'django.utils.log.AdminEmailHandler'
            },
            'sentry': {
                'level': 'ERROR',
                'class':
                'raven.contrib.django.raven_compat.handlers.SentryHandler',
                'formatter': 'complete',
                'filters': ['request_id'],
            },
        },
        'loggers': {
            'django': {
                'handlers': ['null'],
                'propagate': False,
                'level': 'INFO',
            },
            'django.request': {
                'handlers': ['mail_admins', 'console'],
                'level': 'ERROR',
                'propagate': False,
            },
            'django.server': {
                'handlers': ['console'],
                'level': 'INFO',
                'propagate': False,
            },
            'hello_world': {
                'handlers': ['console'],
                'level': 'INFO',
                'propagate': False,
            },
            '': {
                'handlers': ['console', 'sentry'],
                'level': 'ERROR',
                'propagate': True,
            },
        }
    }

    # MIDDLEWARE SETTINGS
    # --------------------------------------------------------------------------
    MIDDLEWARE = [
        # TODO: Re-enable this.
        # 'corsheaders.middleware.CorsMiddleware',
        'log_request_id.middleware.RequestIDMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'whitenoise.middleware.WhiteNoiseMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    # CACHE SETTINGS
    # --------------------------------------------------------------------------
    # See https://cloud.google.com/appengine/docs/flexible/java/upgrading#memcache_service
    # See https://cloud.google.com/appengine/docs/flexible/python/using-redislabs-memcache
    CACHES = {
        'default': {
            'BACKEND':
            'django.core.cache.backends.memcached.PyLibMCCache',
            'LOCATION':
            values.Value('',
                         environ_name='CACHE_URL_DEFAULT',
                         environ_required=True),
            'OPTIONS': {
                'BINARY':
                True,
                'USERNAME':
                values.Value('',
                             environ_name='CACHE_USERNAME_DEFAULT',
                             environ_required=True),
                'PASSWORD':
                values.SecretValue(environ_name='CACHE_PASSWORD_DEFAULT'),
            }
        }
    }

    # django-allauth SETTINGS
    # --------------------------------------------------------------------------
    ACCOUNT_ALLOW_REGISTRATION = True
    ACCOUNT_AUTHENTICATION_METHOD = 'username'
    ACCOUNT_EMAIL_REQUIRED = True
    ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
    ACCOUNT_ADAPTER = 'aperte.users.adapters.AccountAdapter'
    SOCIALACCOUNT_ADAPTER = 'aperte.users.adapters.SocialAccountAdapter'

    # raven SETTINGS
    # --------------------------------------------------------------------------
    RELEASE_VERSION = get_release()
    SENTRY_CLIENT = 'raven.contrib.django.raven_compat.DjangoClient'
    RAVEN_CONFIG = {
        'dsn':
        values.Value('', environ_name='SENTRY_DSN'),
        'environment':
        values.Value('production', environ_name='SENTRY_ENVIRONMENT'),
        'release':
        RELEASE_VERSION,
    }

    SITE_INFO = {
        'RELEASE_VERSION': RELEASE_VERSION,
        'IS_RAVEN_INSTALLED': RAVEN_CONFIG['dsn'] is not ''
    }
Exemplo n.º 22
0
 def FRONTEND_URL(self):
     return values.URLValue(self.SITE_URL)
Exemplo n.º 23
0
class Base(Configuration):
    """Base configuration for our webapps."""

    # Set in environment
    ADMIN_USER: dict = values.DictValue()
    SECRET_KEY: str = values.SecretValue()

    # Required to override
    APP_NAME: str = RequiredValue()
    SITE_URL: str = RequiredValue()
    ALLOWED_HOSTS: List[str] = RequiredValue()
    ADMINS: List[Tuple[str, str]] = RequiredValue()
    MANAGERS: List[Tuple[str, str]] = RequiredValue()

    # Services
    CELERY_BROKER_URL = values.Value('redis://',
                                     environ_name='CELERY_BROKER_URL')
    DATABASES = values.DatabaseURLValue(environ_required=True)

    # Storage
    DEFAULT_FILE_STORAGE = 'ionata_settings.storage.MediaS3'
    STATICFILES_STORAGE = 'ionata_settings.storage.StaticS3'
    AWS_S3_REGION_NAME = values.Value(environ_required=True)
    AWS_STORAGE_BUCKET_NAME = values.Value(environ_required=True)
    AWS_S3_ENDPOINT_URL = values.URLValue(environ_required=True)
    AWS_ACCESS_KEY_ID = values.SecretValue()
    AWS_SECRET_ACCESS_KEY = values.SecretValue()

    # Core
    DEBUG = False

    @property
    def INSTALLED_APPS(self):
        return [
            # Our defaults
            'minimal_user',
            'corsheaders',
            'anymail',
            'django_extensions',
            'storages',
            'django_celery_beat',
            'django_celery_results',

            # Core django apps
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'django.contrib.sites',
        ]

    MIDDLEWARE = [
        'debug_toolbar.middleware.DebugToolbarMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'django.middleware.security.SecurityMiddleware',
    ]
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.i18n',
                    'django.template.context_processors.media',
                    'django.template.context_processors.static',
                    'django.template.context_processors.tz',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]
    ROOT_URLCONF = 'webapp.urls'
    WSGI_APPLICATION = 'webapp.wsgi.application'
    SITE_ID = 1

    # i18n
    LANGUAGE_CODE = 'en-AU'
    TIME_ZONE = 'UTC'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = True

    # Auth
    ANONYMOUS_USER_ID = -1
    AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']
    AUTH_USER_MODEL = 'minimal_user.User'
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': f'{_pw_validation}.UserAttributeSimilarityValidator'
        },
        {
            'NAME': f'{_pw_validation}.MinimumLengthValidator'
        },
        {
            'NAME': f'{_pw_validation}.CommonPasswordValidator'
        },
        {
            'NAME': f'{_pw_validation}.NumericPasswordValidator'
        },
    ]

    # Security
    INTERNAL_IPS = ['127.0.0.1']
    SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
    SESSION_COOKIE_PATH = '/backend/'
    CSRF_COOKIE_PATH = '/backend/'
    SESSION_COOKIE_SECURE = True
    CSRF_COOKIE_SECURE = True
    AWS_AUTO_CREATE_BUCKET = False
    AWS_DEFAULT_ACL = 'private'
    AWS_BUCKET_ACL = 'private'

    @property
    def CORS_ORIGIN_WHITELIST(self):
        return self.ALLOWED_HOSTS

    @property
    def CSRF_TRUSTED_ORIGINS(self):
        return self.CORS_ORIGIN_WHITELIST

    # URLs
    MEDIA_URL = '/assets/media/'
    STATIC_URL = '/assets/static/'

    # Celery
    CELERY_BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 3600}  # 1 hour.
    CELERY_RESULT_BACKEND = 'django-db'
    CELERY_TIMEZONE = 'UTC'
    CELERY_ENABLE_UTC = True
    CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'

    @property
    def CELERY_APP_NAME(self):
        return self.APP_NAME

    # Email
    @property
    def EMAIL_SUBJECT_PREFIX(self):
        return f'[Django - {self.APP_NAME}] '

    @property
    def DEFAULT_FROM_EMAIL(self):
        return f'no-reply@{self.URL.hostname}'

    @property
    def SERVER_EMAIL(self):
        return f'no-reply@{self.URL.hostname}'

    @property
    def MAILGUN_SENDER_DOMAIN(self):
        return f'mailgun.{self.URL.hostname}'

    # Misc properties
    @property
    def URL(self):
        return urlparse(self.SITE_URL)

    @property
    def FRONTEND_URL(self):
        return self.SITE_URL
Exemplo n.º 24
0
class BaseConfig(Configuration):
    DEBUG = values.BooleanValue(False)
    TEMPLATE_DEBUG = values.BooleanValue(DEBUG)
    DATABASES = values.DatabaseURLValue(
        'postgres://%2Fvar%2Flib%2Fpostgresql/sls_blog')
    SECRET_KEY = values.SecretValue()
    CACHES = values.CacheURLValue('locmem://default')

    # Build paths inside the project like this: BASE_DIR / 'subdir'.
    BASE_DIR = (Path(__file__).parent / '../..').resolve(strict=True)

    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/

    ALLOWED_HOSTS = []
    AUTH_USER_MODEL = 'slsblog_auth.User'
    # Application definition

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'corsheaders',
        'wagtail.contrib.forms',
        'wagtail.contrib.redirects',
        "wagtail.contrib.search_promotions",
        "wagtail.contrib.modeladmin",
        'wagtail.embeds',
        'wagtail.sites',
        'wagtail.users',
        'wagtail.snippets',
        'wagtail.documents',
        'wagtail.images',
        'wagtail.search',
        'wagtail.admin',
        'wagtail.core',
        'modelcluster',
        'taggit',
        'wagtail.api.v2',
        'rest_framework',
        "channels",
        "graphql_ws.django",
        "graphene_django",
        "grapple",
        'sls_blog.auth',
        'sls_blog.cms',
        'wagtail_headless_preview',
    ]

    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES':
        ['rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'],
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.BasicAuthentication',
            'rest_framework.authentication.SessionAuthentication',
            'rest_framework_simplejwt.authentication.JWTAuthentication',
        )
    }
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'wagtail.contrib.redirects.middleware.RedirectMiddleware',
    ]

    ROOT_URLCONF = 'sls_blog.urls'
    WAGTAIL_SITE_NAME = 'Stevenlsjr Blog'
    WAGTAIL_I18N_ENABLED = True
    LANGUAGES = WAGTAIL_CONTENT_LANGUAGES = [
    ('en-us', _("English (United States)")),
    ('en-gb', _("English (United Kingdom)")),
    ('es-es', _("Spanish (Spain)")),
    ('es-mx', _("Spanish (Mexico)")),
]

    CORS_ORIGIN_WHITELIST = values.ListValue(default=[])
    CORS_ORIGIN_ALLOW_ALL = values.BooleanValue(default=False)
    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

    WSGI_APPLICATION = 'sls_blog.wsgi.application'
    # ASGI_APPLICATION = 'sls_blog.asgi.application'
    ASGI_APPLICATION = "graphql_ws.django.routing.application"

    # Password validation
    # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME':
            'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]

    # Internationalization
    # https://docs.djangoproject.com/en/3.1/topics/i18n/

    LANGUAGE_CODE = 'en-us'

    TIME_ZONE = 'UTC'

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/3.1/howto/static-files/

    DEFAULT_FILE_STORAGE = values.Value(
        'django.core.files.storage.FileSystemStorage')
    STATICFILES_STORAGE = values.Value(
        'django.contrib.staticfiles.storage.StaticFilesStorage')

    AZURE_ACCOUNT_NAME = values.Value(environ_required=False)
    AZURE_ACCOUNT_KEY = values.Value(environ_required=False)
    AZURE_CONTAINER = values.Value(environ_required=False)
    PUBLIC_AZURE_CONTAINER = values.Value(environ_required=False)
    AZURE_CONNECTION_STRING = values.Value(default=None,
                                           environ_required=False)
    AZURE_CUSTOM_CONNECTION_STRING = values.Value(default=None,
                                                  environ_required=False)
    PUBLIC_AZURE_CONTAINER = values.Value(environ_required=False)
    STATIC_URL = values.Value('/static/')
    MEDIA_URL = values.Value('/media/')
    STATIC_ROOT = values.PathValue(BASE_DIR / '.static')
    MEDIA_ROOT = values.PathValue(BASE_DIR / '.media')

    def GRAPHENE(self):
        cfg = {
            "SCHEMA": "grapple.schema.schema",
            "MIDDLEWARE": ["grapple.middleware.GrappleMiddleware"],
            "SUBSCRIPTION_PATH": "/subscriptions"
        }
        if self.DEBUG:
            cfg['MIDDLEWARE'].insert(
                0, 'graphene_django.debug.DjangoDebugMiddleware')
        return cfg

    GRAPPLE = {
        'APPS': {
            "slsblog_cms": ""
        },
        'EXPOSE_GRAPHIQL': values.BooleanValue(True)
    }

    BASE_URL = values.URLValue('http://localhost:8000')

    HEADLESS_PREVIEW_CLIENT_URLS = values.DictValue({
        'default':
        'http://localhost:3000/preview',
    })
    HEADLESS_PREVIEW_LIVE = values.BooleanValue(True)
Exemplo n.º 25
0
class Base(Core):
    """Settings that may change per-environment, some with defaults."""
    # General settings
    DEBUG = values.BooleanValue(False)
    ADMINS = values.SingleNestedListValue([])

    # Remote services
    DATABASES = values.DatabaseURLValue(
        'postgres://postgres@localhost/normandy')
    GEOIP2_DATABASE = values.Value(
        os.path.join(Core.BASE_DIR, 'GeoLite2-Country.mmdb'))
    # Email settings
    EMAIL_HOST_USER = values.Value()
    EMAIL_HOST = values.Value()
    EMAIL_PORT = values.IntegerValue(587)
    EMAIL_USE_TLS = values.BooleanValue(True)
    EMAIL_HOST_PASSWORD = values.Value()
    EMAIL_BACKEND = values.Value('django.core.mail.backends.smtp.EmailBackend')
    RAVEN_CONFIG = {
        'dsn': values.URLValue(None, environ_name='RAVEN_CONFIG_DSN'),
    }
    PROD_DETAILS_STORAGE = values.Value(
        'normandy.recipes.storage.ProductDetailsRelationalStorage')
    # statsd
    STATSD_HOST = values.Value('localhost')
    STATSD_PORT = values.IntegerValue(8125)
    STATSD_IPV6 = values.BooleanValue(False)
    STATSD_PREFIX = values.Value('normandy')
    STATSD_MAXUDPSIZE = values.IntegerValue(512)

    # Security settings
    SECRET_KEY = values.SecretValue()
    ALLOWED_HOSTS = values.ListValue([])
    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME':
            'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.MinimumLengthValidator'
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.CommonPasswordValidator'
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.NumericPasswordValidator'
        },
    ]
    PASSWORD_HASHERS = values.ListValue([
        'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
        'django.contrib.auth.hashers.PBKDF2PasswordHasher',
    ])
    USE_X_FORWARDED_HOST = values.BooleanValue(False)
    SECURE_PROXY_SSL_HEADER = values.TupleValue()
    SECURE_HSTS_SECONDS = values.IntegerValue(3600)
    SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True)
    CSRF_COOKIE_HTTPONLY = values.BooleanValue(True)
    CSRF_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_SSL_REDIRECT = values.BooleanValue(True)
    SECURE_REDIRECT_EXEMPT = values.ListValue([])
    SESSION_COOKIE_SECURE = values.BooleanValue(True)
    SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True)
    SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True)
    X_FRAME_OPTIONS = values.Value('DENY')

    # Media and static settings
    STATIC_URL = values.Value('/static/')
    STATIC_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'static'))
    MEDIA_URL = values.Value('/media/')
    MEDIA_ROOT = values.Value(os.path.join(Core.BASE_DIR, 'media'))
    STATICFILES_STORAGE = values.Value(
        'normandy.storage.GzipManifestPipelineStorage')
    # Overwrite old files when uploading media.
    DEFAULT_FILE_STORAGE = values.Value(
        'storages.backends.overwrite.OverwriteStorage')
    # URL that the CDN exists at to front cached parts of the site, if any.
    CDN_URL = values.URLValue(None)

    # Normandy settings
    CAN_EDIT_ACTIONS_IN_USE = values.BooleanValue(False)
    ADMIN_ENABLED = values.BooleanValue(True)
    ACTION_IMPLEMENTATION_CACHE_TIME = values.IntegerValue(60 * 60 * 24 * 365)
Exemplo n.º 26
0
class Common(Configuration):
    BACKEND_DAEMON = values.Value(
        'http://back:8000', environ_prefix='ORE')
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql_psycopg2',
            'NAME': values.Value('ore', environ_name='DB_NAME', environ_prefix='ORE'),
            'USER': values.Value('ore', environ_name='DB_USER', environ_prefix='ORE'),
            'PASSWORD': values.Value('ore', environ_name='DB_PASSWORD', environ_prefix='ORE'),
            'HOST': values.Value('localhost', environ_name='DB_HOST', environ_prefix='ORE'),
            'PORT': values.Value('', environ_name='DB_PORT', environ_prefix='ORE'),
        }
    }
    # Environment variable "SERVER" contains the host name of the server
    ALLOWED_HOSTS = ['localhost', '127.0.0.1', values.Value(
        'xxx', environ_prefix='ORE', environ_name='SERVER')]
    # Environment variable "SERVER_URL" contains the full URL for the server
    SERVER = str(values.Value(
        'xxx', environ_prefix='ORE', environ_name='SERVER_URL'))
    FEEDBACK_PAGE = values.URLValue(
        'https://groups.google.com/forum/#!forum/ore-support', environ_prefix='ORE')
    TERMS_PAGE = values.Value('/about/', environ_prefix='ORE')
    PRIVACY_PAGE = values.Value('/privacy/', environ_prefix='ORE')
    AUTH_PROFILE_MODULE = 'ore.UserProfile'
    CORS_ORIGIN_ALLOW_ALL = True
    EMAIL_HOST = 'localhost'
    EMAIL_SUBJECT_PREFIX = '[ORE] '
    LANGUAGE_CODE = 'en-en'
    LOGIN_REDIRECT_URL = '/projects/'
    LOGIN_URL = '/'
    REQUIRE_BASE_URL = 'script'
    REQUIRE_BUILD_PROFILE = '../lib/requirejs/require_build_profile.js'
    REQUIRE_JS = '../lib/requirejs/require-jquery.js'
    ROOT_URLCONF = 'ore.urls'
    MEDIA_ROOT = ''
    MEDIA_URL = ''
    USE_X_FORWARDED_HOST = True
    SEND_BROKEN_LINK_EMAILS = False
    SERVER_EMAIL = values.Value('NOT_SET', environ_prefix='ORE')
    SITE_ID = 1
    SOCIAL_AUTH_URL_NAMESPACE = 'social'
    SOCIAL_AUTH_FIELDS_STORED_IN_SESSION = ['next', ]
    SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_TWITTER_KEY = values.Value('NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_TWITTER_SECRET = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_LIVE_CLIENT_ID = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_LIVE_CLIENT_SECRET = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_YAHOO_OAUTH2_KEY = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_YAHOO_OAUTH2_SECRET = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_GITHUB_KEY = values.Value('NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_GITHUB_SECRET = values.Value(
        'NOT_SET', environ_prefix='ORE')
    SOCIAL_AUTH_PIPELINE = (
        'social.pipeline.social_auth.social_details',
        'social.pipeline.social_auth.social_uid',
        'social.pipeline.social_auth.auth_allowed',
        'social.pipeline.social_auth.social_user',
        'social.pipeline.user.get_username',
        # Transition to 0.7.0 installation for existing users
        'social.pipeline.social_auth.associate_by_email',
        'social.pipeline.user.create_user',
        'social.pipeline.social_auth.associate_user',
        'social.pipeline.social_auth.load_extra_data',
        'social.pipeline.user.user_details'
    )

    STATICFILES_DIRS = ('ore/static',)
    STATICFILES_STORAGE = 'require.storage.OptimizedStaticFilesStorage'
    STATIC_ROOT = 'ore/static-release/'
    STATIC_URL = '/static/'
    TEST_RUNNER = 'django.test.runner.DiscoverRunner'
    TIME_ZONE = 'UTC'      # setting this to None doesn't work on fresh Linux systems
    USE_I18N = False
    USE_L10N = True
    USE_TZ = False
    WSGI_APPLICATION = 'ore.wsgi.application'
    ROBOTS_USE_SITEMAP = False

    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    )

    TEMPLATE_LOADERS = (
        'django.template.loaders.filesystem.Loader',
        'django.template.loaders.app_directories.Loader',
    )

    TEMPLATE_CONTEXT_PROCESSORS = (
        'django.template.context_processors.debug',
        'django.core.context_processors.static',
        'django.contrib.auth.context_processors.auth',
        'django.contrib.messages.context_processors.messages',
        'social.apps.django_app.context_processors.backends',
        'social.apps.django_app.context_processors.login_redirect'
    )

    MIDDLEWARE_CLASSES = (
        'django.middleware.common.CommonMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'ore.middleware.HttpErrorMiddleware',
    )

    INSTALLED_APPS = (
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'django.contrib.admin',
        'django.contrib.admindocs',
        'django.contrib.sites',
        'robots',
        'require',
        'social.apps.django_app.default',
        'tastypie',
        'ore'
    )

    AUTHENTICATION_BACKENDS = (
        'django.contrib.auth.backends.ModelBackend',
        'social.backends.google.GoogleOAuth2',
        'social.backends.twitter.TwitterOAuth',
        'social.backends.yahoo.YahooOAuth2',
        'social.backends.open_id.OpenIdAuth',
        'social.backends.live.LiveOAuth2',
        'social.backends.github.GithubOAuth2'
    )

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'filters': {
            'require_debug_false': {
                '()': 'django.utils.log.RequireDebugFalse'
            },
            'require_debug_true': {
                '()': 'django.utils.log.RequireDebugTrue'
            },
        },
        'formatters': {
            'verbose': {
                'format': "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s"
            },
            'simple': {
                'format': '%(levelname)s %(message)s'
            },
        },
        'handlers': {
            'console': {
                'level': 'DEBUG',
                'filters': ['require_debug_true'],
                'class': 'logging.StreamHandler'
            },
            'mail_admins': {
                'level': 'ERROR',
                'class': 'django.utils.log.AdminEmailHandler',
                'filters': ['require_debug_false'],
            },
            'False': {
                'level': 'DEBUG',
                'class': 'logging.NullHandler',
            },
        },
        'loggers': {
            'django.request': {
                'handlers': ['mail_admins', 'console'],
                'level': 'ERROR',
                'propagate': True,
            },
            'ore': {
                'handlers': ['console', ],
                'level': 'DEBUG',
                'propagate': True,
            },
            'social': {
                'handlers': ['console', ],
                'level': 'DEBUG',
                'propagate': True,
            },

        }
    }
Exemplo n.º 27
0
class BaseSettings(Configuration):
    """
    Django settings for qcat project.

    For more information on this file, see
    https://docs.djangoproject.com/en/dev/topics/settings/

    For the full list of settings and their values, see
    https://docs.djangoproject.com/en/dev/ref/settings/
    """

    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = join(dirname(dirname(dirname(dirname(__file__)))))

    # SECURITY WARNING: don't run with debug turned on in production!
    DEBUG = values.BooleanValue(default=False)

    # Quick-start development settings - unsuitable for production
    # See https://docs.djangoproject.com/en/dev/howto/deployment/checklist/

    # Application definition
    INSTALLED_APPS = (
        'django.contrib.contenttypes',
        'grappelli.dashboard',
        'grappelli',
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.sitemaps',
        'django.contrib.staticfiles',
        'django.contrib.humanize',
        'compressor',
        'cookielaw',
        'corsheaders',
        'django_extensions',
        'django_filters',
        'easy_thumbnails',
        'easy_thumbnails.optimize',
        'floppyforms',
        'imagekit',
        'maintenancemode',
        'rest_framework',
        'rest_framework_swagger',
        'sekizai',
        'wkhtmltopdf',
        # Custom apps
        'accounts',
        'api',
        'approaches',
        'configuration',
        'qcat',
        'questionnaire',
        'notifications',
        'sample',
        'samplemulti',
        'samplemodule',
        'search',
        'summary',
        'technologies',
        'unccd',
        'watershed',
        'wocat',
        'cca',
        'cbp',
    )

    MIDDLEWARE_CLASSES = (
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.security.SecurityMiddleware',
        'django.middleware.locale.LocaleMiddleware',
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'maintenancemode.middleware.MaintenanceModeMiddleware',
        'qcat.middleware.ProfilerMiddleware',
    )

    ROOT_URLCONF = 'qcat.urls'

    WSGI_APPLICATION = 'qcat.wsgi.application'

    # Internationalization
    # https://docs.djangoproject.com/en/dev/topics/i18n/
    LANGUAGE_CODE = 'en'

    LOCALE_PATHS = (
        join(BASE_DIR, 'locale'),
    )

    # The first language is the default language.
    # Important: If you add languages here, make sure to add a placeholder of
    # the infographic in src/assets/img/infographics (make a copy of the English
    # version)
    LANGUAGES = (
        ('en', _('English')),
        ('fr', _('French')),
        ('es', _('Spanish')),
        ('ru', _('Russian')),
        ('zh', _('Chinese')),
        ('km', _('Khmer')),
        ('lo', _('Lao')),
        ('ar', _('Arabic')),
        ('pt', _('Portuguese')),
        ('af', _('Afrikaans')),
        ('th', _('Thai')),
        ('mn', _('Mongolian')),
    )
    # languages with extraordinarily long words that need 'forced' line breaks
    # to remain consistent in the box-layout.
    WORD_WRAP_LANGUAGES = [
        'km',
        'lo',
        'th',
    ]

    TIME_ZONE = 'Europe/Zurich'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = True
    BASE_URL = values.Value(environ_prefix='', default='https://qcat.wocat.net')

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/dev/howto/static-files/
    STATIC_URL = '/static/'
    STATIC_ROOT = join(BASE_DIR, '..', 'static')
    STATICFILES_DIRS = (
        join(BASE_DIR, 'static'),
    )
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
        'compressor.finders.CompressorFinder',
    )

    MEDIA_URL = '/upload/'
    MEDIA_ROOT = join(BASE_DIR, '..', 'upload')

    UPLOAD_VALID_FILES = {
        'image': (
            ('image/jpeg', 'jpg'),
            ('image/png', 'png'),
            ('image/gif', 'gif'),
        ),
        'document': (
            ('application/pdf', 'pdf'),
        )
    }
    UPLOAD_MAX_FILE_SIZE = 3145728  # 3 MB
    UPLOAD_IMAGE_THUMBNAIL_FORMATS = (
        ('default', (640, 480)),
        ('small', (1024, 768)),
        ('medium', (1440, 1080)),
        # 'large' is the original uploaded image.
    )
    THUMBNAIL_ALIASES = {
        'summary': {
            'screen': {
                'header_image': {
                    'size': (1542, 767),
                    'upscale': True,
                    'crop': True,
                    'target': (50, 50),
                },
                'half_height': {
                    'size': (640, 640),
                    'upscale': True,
                    'crop': True,
                },
                'map': {
                    'size': (560, 0)
                },
                'flow_chart': {
                    'size': (900, 0),
                    'upscale': False
                },
                'flow_chart_half_height': {
                    'size': (640, 640),
                    'upscale': True,
                }
            },
            'print': {
                'header_image': {
                    'size': (6168, 3068),
                    'crop': True,
                    'upscale': True,
                },
                'half_height': {
                    'size': (2560, 2560),
                    'upscale': True,
                    'crop': True,
                },
                'map': {
                    'size': (2240, 0)
                },
                'flow_chart': {
                    'size': (3600, 0),
                    'upscale': False
                },
                'flow_chart_half_height': {
                    'size': (2560, 2560),
                    'upscale': True,
                }
            }
        }
    }

    SUMMARY_PDF_PATH = join(MEDIA_ROOT, 'summary-pdf')

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [
                join(BASE_DIR, 'templates'),
            ],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.contrib.auth.context_processors.auth',
                    'django.template.context_processors.debug',
                    'django.template.context_processors.i18n',
                    'django.template.context_processors.media',
                    'django.template.context_processors.static',
                    'django.template.context_processors.tz',
                    'django.contrib.messages.context_processors.messages',
                    'django.template.context_processors.request',
                    'sekizai.context_processors.sekizai',
                    'qcat.context_processors.template_settings'
                ],
            }
        }
    ]



    AUTH_USER_MODEL = 'accounts.User'
    AUTHENTICATION_BACKENDS = (
        'accounts.authentication.WocatCMSAuthenticationBackend',
    )
    REACTIVATE_WOCAT_ACCOUNT_URL = values.URLValue(
        environ_prefix='', default='https://wocat.net/accounts/reactivate/'
    )
    LOGIN_URL = 'login'

    GRAPPELLI_ADMIN_TITLE = 'QCAT Administration'
    GRAPPELLI_INDEX_DASHBOARD = 'qcat.dashboard.CustomIndexDashboard'

    # Elasticsearch settings
    ES_HOST = values.Value(default='localhost', environ_prefix='')
    ES_PORT = values.IntegerValue(default=9200, environ_prefix='')
    ES_INDEX_PREFIX = values.Value(default='qcat_', environ_prefix='')
    # For Elasticsearch >= 2.3: https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking-changes-2.3.html  # noqa
    ES_NESTED_FIELDS_LIMIT = values.IntegerValue(default=250, environ_prefix='')
    # For each language (as set in the setting ``LANGUAGES``), a language
    # analyzer can be specified. This helps to analyze the text in the
    # corresponding language for better search results.
    # https://www.elastic.co/guide/en/elasticsearch/reference/1.6/analysis-lang-analyzer.html  # noqa
    ES_ANALYZERS = (
        ('en', 'english'),
        ('es', 'spanish'),
    )
    # https://www.elastic.co/guide/en/elasticsearch/reference/2.0/query-dsl-query-string-query.html#_reserved_characters
    ES_QUERY_RESERVED_CHARS = ['\\', '+', '-', '=', '&&', '||', '>', '<', '!', '(', ')', '{', '}', '[', ']', '^', '"',
                               '~', '*', '?', ':', '/']

    MESSAGE_TAGS = {
        messages.INFO: 'secondary',
    }

    # Allow various formats to communicate with the API.
    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES': (
            'rest_framework.parsers.JSONParser',
            'rest_framework_xml.parsers.XMLParser',
        ),
        'DEFAULT_RENDERER_CLASSES': (
            'rest_framework.renderers.JSONRenderer',
            'rest_framework_xml.renderers.XMLRenderer',
            'rest_framework_csv.renderers.CSVRenderer',
        ),
        'DEFAULT_THROTTLE_RATES': {
            'anon': '10/day',
            'user': '******',
        },
        'DEFAULT_VERSIONING_CLASS':
            'rest_framework.versioning.NamespaceVersioning',
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 25,
    }
    SWAGGER_SETTINGS = {
        'DOC_EXPANSION': 'list',
        'JSON_EDITOR': True,
        'VALIDATOR_URL': None,
    }
    API_PAGE_SIZE = values.IntegerValue(default=25, environ_prefix='')

    CORS_ORIGIN_WHITELIST = values.ListValue(environ_prefix='', default=[])

    DATABASES = values.DatabaseURLValue(environ_required=True)

    ALLOWED_HOSTS = values.ListValue(default=['localhost', '127.0.0.1'])

    SECRET_KEY = values.SecretValue(environ_required=True)

    # The base URL of the REST API used for authentication
    AUTH_API_URL = values.Value(environ_prefix='', default='https://www.wocat.net/api/v1/')

    # The username used for API login
    AUTH_API_USER = values.Value(environ_prefix='')

    # The key used for API login
    AUTH_API_KEY = values.Value(environ_prefix='')
    AUTH_API_TOKEN = values.Value(environ_prefix='')

    # The URL of the WOCAT authentication form. Used to handle both login
    # and logout
    AUTH_LOGIN_FORM = values.Value(
        environ_prefix='',
        default='https://dev.wocat.net/en/sitefunctions/login.html'
    )
    AUTH_COOKIE_NAME = values.Value(default='fe_typo_user', environ_prefix='')

    # Specify specific editions to be used in the filter. If not specified,
    # always the latest edition of a configuration is used. Specify specific
    # editions as a dict in the env.
    # Example to use edition 2015 to filter Technologies:
    # {"technologies": "2015"}
    FILTER_EDITIONS = values.DictValue(default={}, environ_prefix='')

    # https://raw.githubusercontent.com/SeleniumHQ/selenium/master/py/CHANGES
    # for the latest supported firefox version.
    TESTING_FIREFOX_PATH = values.Value(environ_prefix='')
    TESTING_CHROMEDRIVER_PATH = values.Value(
        environ_prefix='', default='/usr/local/bin/chromedriver')
    TESTING_POP_BROWSER = values.BooleanValue(environ_prefix='', default=False)

    # Flag for caching of the whole configuration object. Sections are always cached.
    USE_CACHING = values.BooleanValue(default=True)
    # django-cache-url doesn't support the redis package of our choice, set the redis location as
    # common environment (dict)value.
    CACHES = values.DictValue(environ_prefix='')
    KEY_PREFIX = values.Value(environ_prefix='', default='')

    # If set to true, the template 503.html is displayed.
    MAINTENANCE_MODE = values.BooleanValue(environ_prefix='', default=False)
    MAINTENANCE_LOCKFILE_PATH = join(BASE_DIR, 'maintenance.lock')

    # "Feature toggles"
    IS_ACTIVE_FEATURE_MODULE = values.BooleanValue(
        environ_prefix='', default=True
    )
    IS_ACTIVE_FEATURE_WATERSHED = values.BooleanValue(
        environ_prefix='', default=False
    )
    IS_ACTIVE_FEATURE_MEMORY_PROFILER = values.BooleanValue(
        environ_prefix='', default=False
    )

    HOST_STRING_DEV = values.Value(environ_prefix='')
    HOST_STRING_DEMO = values.Value(environ_prefix='')
    HOST_STRING_LIVE = values.Value(environ_prefix='')

    # touch file to reload uwsgi
    TOUCH_FILE_DEV = values.Value(environ_prefix='')
    TOUCH_FILE_DEMO = values.Value(environ_prefix='')
    TOUCH_FILE_LIVE = values.Value(environ_prefix='')

    SENTRY_DSN = values.Value(environ_prefix='')
    SLACK_TOKEN = values.Value(environ_prefix='')

    WARN_HEADER = values.Value(environ_prefix='')
    NEXT_MAINTENANCE = join(BASE_DIR, 'envs/NEXT_MAINTENANCE')
    DEPLOY_TIMEOUT = values.Value(environ_prefix='', default=900)

    # Settings for piwik integration. Tracking happens in the frontend
    # (base template) and backend (API)
    PIWIK_SITE_ID = values.IntegerValue(environ_prefix='', default=None)
    PIWIK_URL = values.Value(environ_prefix='', default='https://webstats.wocat.net/')
    PIWIK_AUTH_TOKEN = values.Value(environ_prefix='')
    PIWIK_API_VERSION = values.IntegerValue(environ_prefix='', default=1)

    # google webdeveloper verification
    GOOGLE_WEBMASTER_TOOLS_KEY = values.Value(environ_prefix='')

    # Google Maps Javascript API key
    GOOGLE_MAPS_JAVASCRIPT_API_KEY = values.Value(environ_prefix='')

    # Mail settings (notification mails)
    DEFAULT_FROM_EMAIL = '*****@*****.**'
    DO_SEND_EMAILS = values.BooleanValue(environ_prefix='', default=True)
    DO_SEND_STAFF_ONLY = values.BooleanValue(environ_prefix='', default=False)

    WOCAT_IMPORT_DATABASE_URL = values.Value(environ_prefix='')
    WOCAT_IMPORT_DATABASE_URL_LOCAL = values.Value(environ_prefix='')
    WOCAT_CONTACT_PAGE = values.Value(
        environ_prefix='',
        default='https://www.wocat.net/about/wocat-secretariat'
    )
    WOCAT_MAILBOX_USER_ID = values.IntegerValue(environ_prefix='')

    # TODO: Temporary test of UNCCD flagging.
    TEMP_UNCCD_TEST = values.ListValue(environ_prefix='')

    CDE_SUBNET_ADDR = values.Value(environ_prefix='', default='0.0.0.')

    # Prevent error when submitting very large forms. Default is 1000.
    # (https://docs.djangoproject.com/en/2.0/ref/settings/#data-upload-max-number-fields)
    DATA_UPLOAD_MAX_NUMBER_FIELDS = 2000
class Base(Configuration, Celery):
    # Web Settings

    SECRET_KEY = values.SecretValue()

    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'ugrryo)w9y0(*i^-zjq+%)=o^g*-0l%l*7!5qzrg3j$y3mtp*$'

    # Password validation
    # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

    @property
    def CACHES(self):
        return {
            'default': {
                'BACKEND': 'django_redis.cache.RedisCache',
                'LOCATION': self.REDIS_URL,
                'OPTIONS': {
                    'COMPRESSOR':
                    'django_redis.compressors.zlib.ZlibCompressor',  # noqa
                    'SERIALIZER':
                    'django_redis.serializers.json.JSONSerializer',  # noqa
                },
            },
        }

    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME':
            'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME':
            'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]

    # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
    BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

    # Internationalization
    # https://docs.djangoproject.com/en/1.10/topics/i18n/

    LANGUAGE_CODE = 'en-us'

    TIME_ZONE = values.Value('UTC', environ_prefix=None)

    USE_I18N = True

    USE_L10N = True

    USE_TZ = True

    # Static files (CSS, JavaScript, Images)
    # https://docs.djangoproject.com/en/1.10/howto/static-files/
    STATIC_URL = '/static/'

    CONN_MAX_AGE = values.IntegerValue(60, environ_prefix=None)

    ALLOWED_HOSTS = values.ListValue([], environ_prefix=None)

    CORS_ORIGIN = values.Value(environ_prefix=None)

    USE_X_FORWARDED_HOST = values.BooleanValue(False, environ_prefix=None)

    # Application definition
    INSTALLED_APPS = [
        'relops_hardware_controller.apps.RelopsHardwareControllerAppConfig',
        'relops_hardware_controller.api',
        'django_celery_results',
        'rest_framework',
    ]

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    ROOT_URLCONF = 'relops_hardware_controller.urls'

    TEMPLATES = [
        {
            'BACKEND': 'django.template.backends.django.DjangoTemplates',
            'DIRS': [],
            'APP_DIRS': True,
            'OPTIONS': {
                'context_processors': [
                    'django.template.context_processors.debug',
                    'django.template.context_processors.request',
                    'django.contrib.auth.context_processors.auth',
                    'django.contrib.messages.context_processors.messages',
                ],
            },
        },
    ]

    WSGI_APPLICATION = 'relops_hardware_controller.wsgi.application'

    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
    SESSION_CACHE_ALIAS = 'default'

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (),
        'DEFAULT_RENDERER_CLASSES':
        ('rest_framework.renderers.JSONRenderer', ),
        'UNAUTHENTICATED_USER':
        '******',
    }

    TASKCLUSTER_CLIENT_ID = values.Value(environ_prefix=None)
    TASKCLUSTER_ACCESS_TOKEN = values.SecretValue(environ_prefix=None)

    TASK_NAMES = values.ListValue([
        'ping',
        'status',
        'reboot',
        'ipmi_off',
        'ipmi_on',
        'ipmi_list',
        'ipmi_cycle',
        'ipmi_reset',
        'reimage',
        'loan',
        'return_loan',
    ],
                                  environ_prefix=None)

    REQUIRED_TASKCLUSTER_SCOPE_SETS = values.SingleNestedListValue(
        [['project:releng:roller:{}'.format(task_name)]
         for task_name in TASK_NAMES.value],
        seq_separator=',',
        environ_prefix=None)

    VALID_WORKER_ID_REGEX = values.Value('^.*', environ_prefix=None)

    # Worker Settings

    NOTIFY_EMAIL = values.Value('*****@*****.**', environ_prefix=None)
    NOTIFY_IRC_CHANNEL = values.Value('#roller', environ_prefix=None)

    BUGZILLA_URL = values.URLValue('https://bugzilla.mozilla.org',
                                   environ_prefix=None)
    BUGZILLA_API_KEY = values.SecretValue(environ_prefix=None)
    BUGZILLA_REOPEN_STATE = values.Value('REOPENED', environ_prefix=None)
    BUGZILLA_REBOOT_TEMPLATE = values.Value(json.dumps(
        dict(
            api_key='${api_key}',
            product='Infrastructure & Operations',
            component='DCOps',
            cc='${cc}',
            summary='${hostname} is unreachable',
            version='unspecified',
            description=
            'Reboot ${hostname} ${ip}\nRequested by ${client_id}\nRelops controller action failed:${log}',
            blocks='${blocks}',
        )),
                                            environ_prefix=None)

    BUGZILLA_WORKER_TRACKER_TEMPLATE = values.Value(json.dumps(
        dict(
            api_key='${api_key}',
            product='Infrastructure & Operations',
            component='CIDuty',
            summary='[${DC}] ${alias} problem tracking',
            version='unspecified',
            alias='${alias}',
        )),
                                                    environ_prefix=None)

    XEN_URL = values.URLValue('', environ_prefix=None)
    XEN_USERNAME = values.Value('', environ_prefix=None)
    XEN_PASSWORD = values.Value('', environ_prefix=None)

    ILO_USERNAME = values.Value('', environ_prefix=None)
    ILO_PASSWORD = values.Value('', environ_prefix=None)

    WORKER_CONFIG = JSONFileValue('',
                                  environ_prefix=None,
                                  environ_name='WORKER_CONFIG_PATH')

    # how many seconds to wait for a machine to go down and come back up
    DOWN_TIMEOUT = values.IntegerValue(60, environ_prefix=None)
    UP_TIMEOUT = values.IntegerValue(300, environ_prefix=None)

    REBOOT_METHODS = values.ListValue(
        [
            'ssh_reboot',
            'ipmi_reset',
            'ipmi_cycle',
            'snmp_reboot',  # snmp pdu for mac minis
            'file_bugzilla_bug',  # give up and file a bug
        ],
        environ_prefix=None)
Exemplo n.º 29
0
class Localdev(Base):
    """Configuration to be used during local development and base class
    for testing"""

    # Override some useful developer settings to be True by default.
    ENABLE_TOKENS_AUTHENTICATION = values.BooleanValue(True)
    DEBUG = values.BooleanValue(default=True)
    DEBUG_PROPAGATE_EXCEPTIONS = values.BooleanValue(default=True)

    # When doing localdev, these defaults will suffice. The minio
    # one forces you to use/test boto3 and the old public symbols URL
    # forces you to use/test the symbol downloader based on requests.get().
    SYMBOL_URLS = values.ListValue(["http://minio:9000/testbucket"])

    # By default, upload all symbols to this when in local dev.
    UPLOAD_DEFAULT_URL = values.Value("http://minio:9000/testbucket")

    # Note! By default the value for 'UPLOAD_TRY_SYMBOLS_URL' becomes
    # the value of 'UPLOAD_DEFAULT_URL' but with a '/try' prefix added.

    # Run this much sooner in local development.
    UPLOAD_REATTEMPT_LIMIT_SECONDS = values.IntegerValue(60)

    @classmethod
    def post_setup(cls):
        super().post_setup()
        # in case we don't find these AWS config variables in the environment
        # we load them from the .env file
        for param in ("ACCESS_KEY_ID", "SECRET_ACCESS_KEY", "DEFAULT_REGION"):
            if param not in os.environ:
                os.environ[param] = values.Value(
                    default="", environ_name=param, environ_prefix="AWS"
                )

    @property
    def VERSION(self):
        # this was breaking in ci
        return {}
        output = subprocess.check_output(
            # Use the absolute path of 'git' here to avoid 'git'
            # not being the git we expect in Docker.
            ["/usr/bin/git", "describe", "--tags", "--always", "--abbrev=0"]
        )  # nosec
        if output:
            return {"version": output.decode().strip()}
        else:
            return {}

    MARKUS_BACKENDS = [
        # Commented out, but uncomment if you want to see all the
        # metrics sent to markus.
        # {
        #     'class': 'markus.backends.logging.LoggingMetrics',
        # },
        {
            "class": "markus.backends.datadog.DatadogMetrics",
            "options": {
                "statsd_host": "statsd",
                "statsd_port": 8125,
                "statsd_namespace": "",
            },
        },
        # {"class": "tecken.markus_extra.LogAllMetricsKeys"},
        # {
        #     'class': 'markus.backends.logging.LoggingRollupMetrics',
        #     'options': {
        #         'logger_name': 'markus',
        #         'leader': 'ROLLUP',
        #         'flush_interval': 60
        #     }
        # },
    ]

    # Set these to smaller numbers for the sake of more easily testing
    # pagination in local development.
    API_UPLOADS_BATCH_SIZE = 10
    API_FILES_BATCH_SIZE = 20

    #
    # Default to the test oidcprovider container for Open ID Connect
    #
    # Client ID and secret must match oidcprovider database
    OIDC_RP_CLIENT_ID = values.IntegerValue(1)
    OIDC_RP_CLIENT_SECRET = values.Value("bd01adf93cfb")
    # Load oidcprovider on public port 8081, without /etc/hosts changes
    OIDC_OP_AUTHORIZATION_ENDPOINT = values.URLValue(
        "http://oidc.127.0.0.1.nip.io:8081/openid/authorize"
    )
    # The backend connects to oidcprovider on docker port 8080
    # Django's URL validator, used in URLValue, doesn't like docker hostnames
    OIDC_OP_TOKEN_ENDPOINT = values.Value("http://oidcprovider:8080/openid/token")
    # Same as token switch from URLValue to Value
    OIDC_OP_USER_ENDPOINT = values.Value("http://oidcprovider:8080/openid/userinfo")
    # Allow non-SSL connection to oidcprovider
    OIDC_VERIFY_SSL = values.BooleanValue(False)
    # Disable NotBlockedInAuth0Middleware
    ENABLE_AUTH0_BLOCKED_CHECK = values.BooleanValue(False)
Exemplo n.º 30
0
class Base(Core):
    """Settings that may change per-environment, some with defaults."""

    SECRET_KEY = values.SecretValue()

    DEBUG = values.BooleanValue(default=False)
    DEBUG_PROPAGATE_EXCEPTIONS = values.BooleanValue(default=False)

    ALLOWED_HOSTS = values.ListValue([])

    # The URL under which this instance is running
    SITE_URL = values.URLValue('http://*****:*****@db/postgres')

    CACHES = {
        'default':
        django_cache_url.config(
            default='redis://redis-cache:6379/0',
            env='REDIS_URL',
        ),
        'store':
        django_cache_url.config(
            default='redis://redis-store:6379/0',
            env='REDIS_STORE_URL',
        )
    }

    LOGGING_USE_JSON = values.BooleanValue(False)

    def LOGGING(self):
        return {
            'version': 1,
            'disable_existing_loggers': False,
            'formatters': {
                'json': {
                    '()': 'dockerflow.logging.JsonLogFormatter',
                    'logger_name': 'tecken',
                },
                'verbose': {
                    'format': '%(levelname)s %(asctime)s %(name)s %(message)s',
                },
            },
            'handlers': {
                'console': {
                    'level': 'DEBUG',
                    'class': 'logging.StreamHandler',
                    'formatter':
                    ('json' if self.LOGGING_USE_JSON else 'verbose'),
                },
                'sentry': {
                    'level':
                    'ERROR',
                    'class': ('raven.contrib.django.raven_compat.handlers'
                              '.SentryHandler'),
                },
            },
            'loggers': {
                'root': {
                    'level': 'INFO',
                    'handlers': ['sentry', 'console'],
                },
                'django.db.backends': {
                    'level': 'ERROR',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'raven': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'sentry.errors': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'tecken': {
                    'level': 'DEBUG',
                    'handlers': ['console'],
                    'propagate': False,
                },
                'request.summary': {
                    'handlers': ['console'],
                    'level': 'DEBUG',
                    'propagate': False,
                },
            },
        }

    SYMBOL_URLS = values.ListValue([
        'https://s3-us-west-2.amazonaws.com/org.mozilla.crash-stats.'
        'symbols-public/v1/',
    ])

    # Number of seconds to wait for a symbol download. If this
    # trips, no error will be raised and we'll just skip using it
    # as a known symbol file.
    # The value gets cached as an empty dict for one hour.
    SYMBOLS_GET_TIMEOUT = values.Value(5)