class MiddlewareMixin: MIDDLEWARE = values.ListValue([]) MIDDLEWARE_FILE = values.Value(None) MIDDLEWARE_FILES = values.ListValue([]) @classmethod def setup(cls): super(MiddlewareMixin, cls).setup() f_list = cls.MIDDLEWARE_FILES or [cls.MIDDLEWARE_FILE] for f in filter(None, f_list): for l in getlines(f): if l.strip() and l.strip() not in cls.MIDDLEWARE: cls.MIDDLEWARE.append(l.strip())
class Prod(Base): DEBUG = False ALLOWED_HOSTS = values.ListValue(default=[".code4.ro"]) CORS_ORIGIN_WHITELIST = values.ListValue(default=[".code4.ro"]) CORS_ORIGIN_REGEX_WHITELIST = values.ListValue(default=["*.code4.ro"]) EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend" EMAIL_USE_TLS = True EMAIL_HOST = values.Value(default="smtp.gmail.com") EMAIL_PORT = 587 EMAIL_HOST_USER = values.Value() EMAIL_HOST_PASSWORD = values.Value() DEFAULT_FROM_EMAIL = values.EmailValue(default="*****@*****.**")
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"
class DevelopmentBaseConfiguration(DebugMixin, ConsoleEmailMixin, MinioStorageMixin, _BaseConfiguration): DEBUG = True SECRET_KEY = 'insecuresecret' ALLOWED_HOSTS = values.ListValue(['localhost', '127.0.0.1']) CORS_ORIGIN_REGEX_WHITELIST = values.ListValue( [r'^https?://localhost:\d+$', r'^https?://127\.0\.0\.1:\d+$']) # INTERNAL_IPS does not work properly when this is run within Docker, since the bridge # sends requests from the host machine via a dedicated IP address INTERNAL_IPS = ['127.0.0.1'] # Setting this allows MinIO to work through network namespace partitions # (e.g. when running within Docker Compose) MINIO_STORAGE_MEDIA_URL = values.Value(None)
class Development(Common): """ The in-development settings and the default configuration. """ DEBUG = values.BooleanValue(True) DEBUG_TOOLBAR = values.BooleanValue(True) ALLOWED_HOSTS = values.ListValue( ['dev.forsa.om', 'forsa-development.herokuapp.com', '127.0.0.1']) INTERNAL_IPS = ['127.0.0.1'] MIDDLEWARE = Common.MIDDLEWARE + [ 'debug_toolbar.middleware.DebugToolbarMiddleware' ] STATIC_URL = '/static/' STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' DEFAULT_FILE_STORAGE = 'django_hashedfilenamestorage.storage.HashedFilenameFileSystemStorage' CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', } }
class Production(Common): """ The in-production settings. """ # Security SESSION_COOKIE_SECURE = values.BooleanValue(True) SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True) SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True) SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True) SECURE_HSTS_SECONDS = values.IntegerValue(31_536_000) SECURE_REDIRECT_EXEMPT = values.ListValue([]) SECURE_SSL_HOST = values.Value(None) SECURE_SSL_REDIRECT = values.BooleanValue(True) SECURE_PROXY_SSL_HEADER = values.TupleValue( ("HTTP_X_FORWARDED_PROTO", "https")) AWS_REGION = values.Value("us-east-1", environ_prefix=None) AWS_ACCESS_KEY_ID = values.SecretValue(environ_prefix=None) AWS_SECRET_ACCESS_KEY = values.SecretValue(environ_prefix=None) AWS_S3_BUCKET_NAME = values.Value(environ_prefix=None) CONTRACTS_DOCUMENT_STORAGE = "django_s3_storage.storage.S3Storage" @property def CACHES(self): return { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": f"{self.REDIS_URL}/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient" }, } }
class Prod(Base): """Production settings (override default values with environment vars""" SECRET_KEY = values.SecretValue() DEBUG = False SASS_OUTPUT_STYLE = 'compressed' # Set like this: DJANGO_ADMINS=Foo,[email protected];Bar,[email protected] ADMINS = values.SingleNestedTupleValue() # Set like this: DJANGO_ALLOWED_HOSTS=foo.com,bar.net ALLOWED_HOSTS = values.ListValue([ '127.0.0.1', 'localhost', 'oldp.local', 'de.oldp.local' ]) # Set like this: DJANGO_LANGUAGES_DOMAINS="{'de.foo.com':'de','fr.foo.com':'fr'}" LANGUAGES_DOMAINS = values.DictValue({ 'localhost:8000': 'en', 'oldp.local:8000': 'en', 'de.oldp.local:8000': 'de', '127.0.0.1:8000': 'de', })
class Staging(Common): """ The in-staging settings. """ ALLOWED_HOSTS = ['carlos-shortener.herokuapp.com', 'cour.fun'] # Security SESSION_COOKIE_SECURE = values.BooleanValue(True) SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True) SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True) SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True) SECURE_HSTS_SECONDS = values.IntegerValue(31536000) SECURE_REDIRECT_EXEMPT = values.ListValue([]) SECURE_SSL_HOST = values.Value(None) SECURE_SSL_REDIRECT = values.BooleanValue(False) #SECURE_PROXY_SSL_HEADER = values.TupleValue( # ('HTTP_X_FORWARDED_PROTO', 'https') #) HOSTNAME = 'cour.fun' EMAIL_BACKEND = "sendgrid_backend.SendgridBackend" SENDGRID_API_KEY = values.SecretValue() SENTRY_DSN = values.SecretValue() @classmethod def post_setup(cls): sentry_sdk.init(dsn=cls.SENTRY_DSN, integrations=[DjangoIntegration()])
class Production(Base): """Production environment settings. You must define the DJANGO_ALLOWED_HOSTS environment variable in Production configuration (and derived configurations): DJANGO_ALLOWED_HOSTS="foo.com,foo.fr" """ ALLOWED_HOSTS = values.ListValue(None) STATICFILES_STORAGE = values.Value( "marsha.core.static.MarshaCompressedManifestStaticFilesStorage") STATIC_POSTPROCESS_IGNORE_REGEX = values.Value( r"^js\/build\/[0-9]*\..*\.js(\.map)?$") STATIC_POSTPROCESS_MAP_IGNORE_REGEX = values.Value( r"^js\/build\/[0-9]*\..*\.js\.map$") AWS_BASE_NAME = values.Value("production") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True # pylint: disable=invalid-name @property def STATIC_URL(self): """Compute the absolute static url used in the lti template.""" return f"//{self.CLOUDFRONT_DOMAIN}/static/"
class Dev(PostgreSQLDatabases, Common): """Settings for development.""" def get_addr(self): if socket.gethostname() == 'vagrant': addr = socket.gethostbyname(socket.gethostname()) else: addr = '127.0.0.1' return addr @property def INTERNAL_IPS(self): return (self.get_addr(),) # devserver must be ahead of django.contrib.staticfiles INSTALLED_APPS = ('devserver',) + Common.INSTALLED_APPS + ('debug_toolbar',) EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' @property def DEVSERVER_DEFAULT_ADDR(self): return self.get_addr() DEVSERVER_ARGS = values.ListValue([]) DEVSERVER_TRUNCATE_SQL = values.BooleanValue(True) DEVSERVER_MODULES = ( 'devserver.modules.sql.SQLRealTimeModule', 'devserver.modules.sql.SQLSummaryModule', 'devserver.modules.profile.ProfileSummaryModule', ) # Beware before activating this! Grappelli has problems with admin # inlines and TEMPLATE_STRING_IF_INVALID. TEMPLATE_STRING_IF_INVALID = values.Value('')
class Local(ProjectDefault): """The local settings.""" # Application definition INSTALLED_APPS = ProjectDefault.INSTALLED_APPS.copy() MIDDLEWARE = ProjectDefault.MIDDLEWARE.copy() # Debug # https://docs.djangoproject.com/en/{{docs_version}}/ref/settings/#debug DEBUG = True # Email URL # https://django-configurations.readthedocs.io/en/stable/values/ EMAIL = values.EmailURLValue("console://") # Django Debug Toolbar # https://django-debug-toolbar.readthedocs.io/en/stable/configuration.html try: import debug_toolbar # noqa except ModuleNotFoundError: # pragma: no cover pass else: # pragma: no cover INTERNAL_IPS = values.ListValue([], environ_name="ALLOWED_HOSTS") INSTALLED_APPS.append("debug_toolbar") MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
class Prod(Common): SECRET_KEY = values.SecretValue() ALLOWED_HOSTS = values.ListValue() DATABASES = { "default": dj_database_url.config(conn_max_age=600, ssl_require=False) } GOOGLE_ANALYTICS_KEY = values.Value()
class MinimalDevelopmentBaseConfiguration( DebugMixin, ConsoleEmailMixin, LoggingMixin, AllauthMixin, StaticFileMixin, DjangoMixin, ComposedConfiguration, ): DEBUG = True SECRET_KEY = 'insecuresecret' ALLOWED_HOSTS = values.ListValue(['localhost', '127.0.0.1']) INTERNAL_IPS = _AlwaysContains() if _is_docker() else ['127.0.0.1'] OAUTH2_PROVIDER = { 'PKCE_REQUIRED': False, 'ALLOWED_REDIRECT_URI_SCHEMES': ['http', 'https'], 'REQUEST_APPROVAL_PROMPT': 'force', } @staticmethod def before_binding(configuration: Type[ComposedConfiguration]) -> None: configuration.INSTALLED_APPS += [ 'oauth2_provider', ]
class Staging(Common): """ The in-staging settings. """ # Security BASE_DIR = os.path.dirname(os.path.dirname(__file__)) SESSION_COOKIE_SECURE = values.BooleanValue(True) SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True) SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True) SECURE_HSTS_INCLUDE_SUBDOMAINS = values.BooleanValue(True) SECURE_HSTS_SECONDS = values.IntegerValue(31536000) SECURE_REDIRECT_EXEMPT = values.ListValue([]) SECURE_SSL_HOST = values.Value(None) SECURE_SSL_REDIRECT = values.BooleanValue(True) SECURE_PROXY_SSL_HEADER = values.TupleValue( ('HTTP_X_FORWARDED_PROTO', 'https') ) WEBPACK_LOADER = { 'DEFAULT': { 'BUNDLE_DIR_NAME': 'bundles/', 'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.prod.json'), } }
class Base(Core): """Settings that may change on a per-environment basis, some with defaults.""" SECRET_KEY = values.SecretValue() DEBUG = values.BooleanValue(False) ALLOWED_HOSTS = values.ListValue([]) # Database # https://docs.djangoproject.com/en/1.10/ref/settings/#databases DATABASES = values.DatabaseURLValue() # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ 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'), ) MAILCHIMP_USERNAME = values.Value() MAILCHIMP_API_KEY = values.Value() MAILCHIMP_LIST_ID = values.Value()
class Production(Common): ALLOWED_HOSTS = values.ListValue(environ_prefix="", default=[]) SECURE_BROWSER_XSS_FILTER = True SESSION_COOKIE_SECURE = True SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SECURE_SSL_REDIRECT = True SECURE_HSTS_SECONDS = values.IntegerValue(environ_prefix="", default=3600) MIDDLEWARE = [ "django.middleware.http.ConditionalGetMiddleware", "django.middleware.gzip.GZipMiddleware", ] + Common.MIDDLEWARE SENTRY_CONFIG = { "dsn": os.getenv("SENTRY_DSN", ""), "environment": _environment, "release": _release, } @classmethod def post_setup(cls): super().post_setup() sentry_sdk.init(integrations=[DjangoIntegration()], **cls.SENTRY_CONFIG, send_default_pii=True)
class Production(Base): # SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") # SECURE_SSL_REDIRECT = True ALLOWED_HOSTS = values.ListValue([]) AWS_ACCESS_KEY_ID = values.Value("") AWS_SECRET_ACCESS_KEY = values.Value("") AWS_STORAGE_BUCKET_NAME = "putztrix-maestro-bucket" AWS_S3_REGION_NAME = "eu-central-1" AWS_DEFAULT_ACL = None AWS_S3_SIGNATURE_VERSION = "s3v4" AWS_S3_CUSTOM_DOMAIN = f"{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com" AWS_S3_OBJECT_PARAMETERS = { "CacheControl": "max-age=86400", } STATIC_LOCATION = "static" STATIC_URL = f"https://{AWS_S3_CUSTOM_DOMAIN}/{STATIC_LOCATION}/" STATICFILES_STORAGE = "apps.invoice.storage_backends.StaticStorage" DEFAULT_FILE_STORAGE = "apps.invoice.storage_backends.MediaStorage" PRIVATE_MEDIA_LOCATION = "media" PRIVATE_FILE_STORAGE = "apps.invoice.storage_backends.MediaStorage" WEASYPRINT_HOST = "weasyprint" X_FRAME_OPTIONS = "SAMEORIGIN" if "SENTRY_DSN" in os.environ: sentry_sdk.init( dsn=os.environ["SENTRY_DSN"], integrations=[DjangoIntegration()], release="1.0", )
class Staging(Base): """ Staging environment settings. Our staging environment is basically attempting to replicate Production, although with smaller machines and fewer constraints. For settings this means we're expecting them to be very similar. """ # Store uploaded files in object storage AWS_ACCESS_KEY_ID = values.Value( environ_name="CELLAR_ADDON_KEY_ID", environ_prefix=None ) AWS_SECRET_ACCESS_KEY = values.Value( environ_name="CELLAR_ADDON_KEY_SECRET", environ_prefix=None ) AWS_S3_ENDPOINT_URL = values.Value() AWS_STORAGE_BUCKET_NAME = values.Value() # Enable unique filenames & compression for static files through WhiteNoise STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # Postgresql config that maps to Clever-Cloud environment variablees DATABASES = { "default": { "ENGINE": values.Value( "django.db.backends.postgresql_psycopg2", environ_name="DATABASE_ENGINE", environ_prefix=None, ), "NAME": values.Value( "partaj", environ_name="POSTGRESQL_ADDON_DB", environ_prefix=None ), "USER": values.Value( "admin", environ_name="POSTGRESQL_ADDON_USER", environ_prefix=None ), "PASSWORD": values.Value( "admin", environ_name="POSTGRESQL_ADDON_PASSWORD", environ_prefix=None ), "HOST": values.Value( "db", environ_name="POSTGRESQL_ADDON_HOST", environ_prefix=None ), "PORT": values.Value( 5432, environ_name="POSTGRESQL_ADDON_PORT", environ_prefix=None ), } } # Actual allowed hosts are specified directly through an environment variable ALLOWED_HOSTS = values.ListValue(None) # Force use of SSL, stop redirect loops by picking up the header that signifies the request # already went through HTTPS SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
class Production(Base): """Production environment settings. You must define the DJANGO_ALLOWED_HOSTS environment variable in Production configuration (and derived configurations): DJANGO_ALLOWED_HOSTS="foo.com,foo.fr" """ ALLOWED_HOSTS = values.ListValue(None) # For static files in production, we want to use a backend that includes a hash in # the filename, that is calculated from the file content, so that browsers always # get the updated version of each file. STATICFILES_STORAGE = values.Value( "marsha.core.storage.ConfigurableManifestS3Boto3Storage" ) # The mapping between the names of the original files and the names of the files distributed # by the backend is stored in a file. # The best practice is to allow this manifest file's name to change for each deployment so # that several versions of the app can run in parallel without interfering with each other. # We make it configurable so that it can be versioned with a deployment stamp in your CI/CD: STATICFILES_MANIFEST_NAME = values.Value("staticfiles.json") AWS_S3_OBJECT_PARAMETERS = { "Expires": "Thu, 31 Dec 2099 20:00:00 GMT", "CacheControl": "max-age=94608000", } AWS_BASE_NAME = values.Value("production") # folder where static will be stored. It matches the path_pattern used # in the cloudfront configuration. AWS_LOCATION = Base.STATIC_URL.lstrip("/") # pattern matching files to ignore when hashing file names and exclude from the # static files manifest STATIC_POSTPROCESS_IGNORE_REGEX = values.Value(r"^js\/[0-9]*\..*\.index\.js$") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True # pylint: disable=invalid-name @property def ABSOLUTE_STATIC_URL(self): """Compute the absolute static url used in the lti template.""" return f"//{self.CLOUDFRONT_DOMAIN}{self.STATIC_URL}" # pylint: disable=invalid-name @property def AWS_STATIC_BUCKET_NAME(self): """AWS Static bucket name. If this setting is set in an environment variable we use it. Otherwise the value is computed with the AWS_BASE_NAME value. """ return os.environ.get( "DJANGO_AWS_STATIC_BUCKET_NAME", f"{self.AWS_BASE_NAME}-marsha-static" )
class Production(Base): """ Production environment settings. You must define the DJANGO_ALLOWED_HOSTS environment variable in Production configuration (and derived configurations): DJANGO_ALLOWED_HOSTS="foo.com,foo.fr" """ # Store uploaded files in object storage AWS_ACCESS_KEY_ID = values.Value( environ_name="CELLAR_ADDON_KEY_ID", environ_prefix=None ) AWS_SECRET_ACCESS_KEY = values.Value( environ_name="CELLAR_ADDON_KEY_SECRET", environ_prefix=None ) AWS_S3_ENDPOINT_URL = values.Value() AWS_STORAGE_BUCKET_NAME = values.Value() # Enable unique filenames & compression for static files through WhiteNoise STATICFILES_STORAGE = "whitenoise.storage.CompressedManifestStaticFilesStorage" # Postgresql config that maps to Clever-Cloud environment variablees DATABASES = { "default": { "ENGINE": values.Value( "django.db.backends.postgresql_psycopg2", environ_name="DATABASE_ENGINE", environ_prefix=None, ), "NAME": values.Value( "partaj", environ_name="POSTGRESQL_ADDON_DB", environ_prefix=None ), "USER": values.Value( "admin", environ_name="POSTGRESQL_ADDON_USER", environ_prefix=None ), "PASSWORD": values.Value( "admin", environ_name="POSTGRESQL_ADDON_PASSWORD", environ_prefix=None ), "HOST": values.Value( "db", environ_name="POSTGRESQL_ADDON_HOST", environ_prefix=None ), "PORT": values.Value( 5432, environ_name="POSTGRESQL_ADDON_PORT", environ_prefix=None ), } } # Actual allowed hosts are specified directly through an environment variable ALLOWED_HOSTS = values.ListValue(None) # Force use of SSL, stop redirect loops by picking up the header that signifies the request # already went through HTTPS SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https") SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
class SecuritySettings: """ Security-related Django settings """ ALLOWED_HOSTS = values.ListValue(default=[]) SECRET_KEY = values.SecretValue()
class Prod(Common): SECRET_KEY = values.SecretValue() ALLOWED_HOSTS = values.ListValue() CLOUDAMQP_URL = values.Value(environ_prefix=None) BROKER_URL = CLOUDAMQP_URL DATABASES = {"default": dj_database_url.config(conn_max_age=600, ssl_require=True)} GOOGLE_ANALYTICS_KEY = values.Value() CITY_COUNCIL_WEBSERVICE = values.Value()
class ProductionReadOnly(Production): """ Settings for a production environment that is read-only. This is used on public-facing webheads. """ EXTRA_MIDDLEWARE = [ # No need for sessions, so removing those middlewares helps us go fast ] ADMIN_ENABLED = values.BooleanValue(False) SILENCED_SYSTEM_CHECKS = values.ListValue( ["security.W001", "security.W003"] # Security middle ware check # CSRF middleware check ) # In ReadOnly mode you have no business using the API to do any writes # anyway. This gives early feedback to that. CORS_ALLOW_METHODS = values.ListValue(["GET", "OPTIONS"])
def STATICFILES_DIRS(self) -> list: if self.STORAGE_TYPE == 's3': return [str(self.BASE_DIR) + '/static'] else: return values.ListValue(default=[ os.path.join(self.BASE_DIR, 'frontend'), ], environ_name='STATICFILES_DIRS', environ_prefix='KRYNEGGER')
class FakeProd(Prod): """Fake Prod during development""" ''' Security ''' ALLOWED_HOSTS = values.ListValue(['*']) NORECAPTCHA_SITE_KEY = None NORECAPTCHA_SECRET_KEY = None ''' Logging ''' ADMINS = values.ListValue([ ('Yatharth', '*****@*****.**'), ]) ''' Convenience ''' STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage' TEMPLATE_STRING_IF_INVALID = 'DEBUG WARNING: undefined template variable [%s] not found'
class Dev(Base): DEBUG = values.BooleanValue(environ_prefix='IT', default=True) SECRET_KEY = values.Value(environ_prefix='IT', default='DEV-KEY ONLY! DONT USE IN PRODUCTION!') DB_HOST = values.Value(environ_prefix='IT', default='localhost') DB_PASSWORD = values.Value(environ_prefix='IT', default='imagetagger') ALLOWED_HOSTS = values.ListValue(environ_prefix='IT', default=['localhost', '127.0.0.1']) DOWNLOAD_BASE_URL = values.Value(environ_prefix='IT', default='localhost')
class Production(Common, Configuration): DEBUG = False ALLOWED_HOSTS = values.ListValue([], separator=' ') SESSION_COOKIE_SECURE = values.BooleanValue(True) SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True) SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True) SECURE_SSL_REDIRECT = values.BooleanValue(True) SECURE_SSL_HOST = values.Value(None) SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
class DevelopmentBaseConfiguration(DebugMixin, ConsoleEmailMixin, MinioStorageMixin, _BaseConfiguration): DEBUG = True SECRET_KEY = 'insecuresecret' ALLOWED_HOSTS = values.ListValue(['localhost', '127.0.0.1']) CORS_ORIGIN_REGEX_WHITELIST = values.ListValue( [r'^https?://localhost:\d+$', r'^https?://127\.0\.0\.1:\d+$']) # When in Docker, the bridge network sends requests from the host machine exclusively via a # dedicated IP address. Since there's no way to determine the real origin address, # consider any IP address (though actually this will only be the single dedicated address) to # be internal. This relies on the host to set up appropriate firewalls for Docker, to prevent # access from non-internal addresses. INTERNAL_IPS = _AlwaysContains() if _is_docker() else ['127.0.0.1'] # Setting this allows MinIO to work through network namespace partitions # (e.g. when running within Docker Compose) MINIO_STORAGE_MEDIA_URL = values.Value(None)
class Staging(Common): """ The in-staging settings. """ ALLOWED_HOSTS = ['forsa-staging.herokuapp.com', 'staging.forsa.om'] DEBUG = values.BooleanValue(True) DEBUG_TOOLBAR = values.BooleanValue(True) MIDDLEWARE = Common.MIDDLEWARE + [ 'debug_toolbar.middleware.DebugToolbarMiddleware' ] INTERNAL_IPS = values.ListValue() # Security SECURE_BROWSER_XSS_FILTER = values.BooleanValue(True) SECURE_CONTENT_TYPE_NOSNIFF = values.BooleanValue(True) SECURE_REDIRECT_EXEMPT = values.ListValue([]) X_FRAME_OPTIONS = 'DENY' # Amazon S3 settings AWS_ACCESS_KEY_ID = values.Value() AWS_SECRET_ACCESS_KEY = values.Value() AWS_STORAGE_BUCKET_NAME = values.Value() AWS_S3_CUSTOM_DOMAIN = values.Value() AWS_S3_OBJECT_PARAMETERS = { 'CacheControl': 'max-age=86400', } # Static assets AWS_LOCATION = 'static' STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' STATIC_URL = "https://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, AWS_LOCATION) # Media assets DEFAULT_FILE_STORAGE = 'forsa.storage_backends.S3HashedFilenameStorage' THUMBNAIL_FORCE_OVERWRITE = True ADMIN_URL = values.Value() CACHES = values.CacheURLValue()
class TemplatesMixin: BASE_DIR = os.getcwd() TEMPLATES_BACKEND = values.Value( 'django.template.backends.django.DjangoTemplates') TEMPLATES_DIRS = values.ListValue([]) TEMPLATES_APP_DIRS = values.BooleanValue(True) TEMPLATES_OPTIONS = {} TEMPLATES_CONTEXT_PROCESSORS = values.ListValue([]) TEMPLATES_CONTEXT_PROCESSORS_FILE = values.Value(None) TEMPLATES_LOADERS = values.ListValue([]) @classmethod def setup(cls): super(TemplatesMixin, cls).setup() path = os.path.join(cls.BASE_DIR, "templates") if not cls.TEMPLATES_DIRS and os.path.exists(path): cls.TEMPLATES_DIRS = [path] cls.TEMPLATES_CONTEXT_PROCESSORS = getlines( cls.TEMPLATES_CONTEXT_PROCESSORS_FILE) if not cls.TEMPLATES_OPTIONS: cls.TEMPLATES_OPTIONS = { 'context_processors': cls.TEMPLATES_CONTEXT_PROCESSORS } if cls.TEMPLATES_LOADERS: cls.TEMPLATES_OPTIONS['loaders'] = cls.TEMPLATES_LOADERS if cls.TEMPLATES_LOADERS: cls.TEMPLATES_APP_DIRS = False if not hasattr(cls, 'TEMPLATES') or not cls.TEMPLATES: cls.TEMPLATES = [{}] if 'BACKEND' not in cls.TEMPLATES[0]: cls.TEMPLATES[0]['BACKEND'] = cls.TEMPLATES_BACKEND if 'DIRS' not in cls.TEMPLATES[0]: cls.TEMPLATES[0]['DIRS'] = cls.TEMPLATES_DIRS if 'APP_DIRS' not in cls.TEMPLATES[0]: cls.TEMPLATES[0]['APP_DIRS'] = cls.TEMPLATES_APP_DIRS if 'OPTIONS' not in cls.TEMPLATES[0]: cls.TEMPLATES[0]['OPTIONS'] = cls.TEMPLATES_OPTIONS if cls.TEMPLATES_CONTEXT_PROCESSORS and 'context_processors' not in cls.TEMPLATES[ 0]['OPTIONS']: cls.TEMPLATES[0]['OPTIONS'][ 'context_processors'] = cls.TEMPLATES_CONTEXT_PROCESSORS if cls.TEMPLATES_LOADERS and 'loaders' not in cls.TEMPLATES[0][ 'OPTIONS']: cls.TEMPLATES[0]['OPTIONS']['loaders'] = cls.TEMPLATES_LOADERS