123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373 |
- ##
- # Copyright (C) 2014 Jessica Tallon & Matt Molyneaux
- #
- # This file is part of Inboxen.
- #
- # Inboxen is free software: you can redistribute it and/or modify
- # it under the terms of the GNU Affero General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # Inboxen is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU Affero General Public License for more details.
- #
- # You should have received a copy of the GNU Affero General Public License
- # along with Inboxen If not, see <http://www.gnu.org/licenses/>.
- ##
- from subprocess import Popen, PIPE
- import datetime
- import os
- import stat
- import warnings
- from django.contrib.messages import constants as message_constants
- from django.core import exceptions, urlresolvers
- from kombu.common import Broadcast, Exchange, Queue
- from kombu.serialization import registry
- import configobj
- import djcelery
- import jsondate
- import validate
- djcelery.setup_loader()
- ##
- # Most configuration can be done via settings.ini
- #
- # The file is searched for in the follow way:
- # 1. The environment variable "INBOXEN_CONFIG", which contains an absolute path
- # 2. ~/.config/inboxen/settings.ini
- # 3. settings.ini in the same folder as this file
- #
- # See inboxen/config_spec.ini for defaults, see below for comments
- ##
- # Shorthand for Django's default database backends
- db_dict = {
- "postgresql": "django.db.backends.postgresql_psycopg2",
- "mysql": "django.db.backends.mysql",
- "oracle": "django.db.backends.oracle",
- "sqlite": "django.db.backends.sqlite3",
- }
- # Shorthand for Django's default database backends
- cache_dict = {
- "database": "django.core.cache.backends.db.DatabaseCache",
- "dummy": "django.core.cache.backends.dummy.DummyCache",
- "file": "django.core.cache.backends.filebased.FileBasedCache",
- "localmem": "django.core.cache.backends.locmem.LocMemCache",
- "memcached": "django.core.cache.backends.memcached.PyLibMCCache",
- }
- is_testing = bool(int(os.getenv('INBOX_TESTING', '0')))
- BASE_DIR = os.path.dirname(__file__)
- if os.path.exists(os.getenv('INBOX_CONFIG', '')):
- CONFIG_PATH = os.getenv('INBOX_CONFIG')
- elif os.path.exists(os.path.expanduser("~/.config/inboxen/settings.ini")):
- CONFIG_PATH = os.path.expanduser("~/.config/inboxen/settings.ini")
- elif os.path.exists(os.path.join(BASE_DIR, "settings.ini")):
- CONFIG_PATH = os.path.join(BASE_DIR, "settings.ini")
- elif is_testing:
- CONFIG_PATH = ""
- else:
- raise exceptions.ImproperlyConfigured("You must provide a settings.ini file")
- # Check that our chosen settings file cannot be interacted with by other users
- try:
- mode = os.stat(CONFIG_PATH).st_mode
- except OSError:
- warnings.warn("Couldn't find settings.ini", ImportWarning)
- else:
- if mode & stat.S_IRWXO != 0:
- warnings.warn("Other users could be able to interact with your settings file. Please check file permissions on %s" % CONFIG_PATH)
- config_spec = os.path.join(BASE_DIR, "inboxen/config_spec.ini")
- config = configobj.ConfigObj(CONFIG_PATH, configspec=config_spec)
- config.validate(validate.Validator())
- # TODO: These could be merged into a custom validator
- try:
- SECRET_KEY = config["general"]["secret_key"]
- except KeyError:
- if is_testing:
- warnings.warn("You haven't set 'secret_key' in your settings.ini", ImportWarning)
- else:
- raise exceptions.ImproperlyConfigured("You must set 'secret_key' in your settings.ini")
- if len(config["general"]["admin_names"]) != len(config["general"]["admin_emails"]):
- raise exceptions.ImproperlyConfigured("You must have the same number of admin_names as admin_emails settings.ini")
- # Admins (and managers)
- ADMINS = zip(config["general"]["admin_names"], config["general"]["admin_emails"])
- # List of hosts allowed
- ALLOWED_HOSTS = config["general"]["allowed_hosts"]
- # Enable debugging - DO NOT USE IN PRODUCTION
- DEBUG = config["general"]["debug"]
- # Alloew new users to register
- ENABLE_REGISTRATION = config["general"]["enable_registration"]
- # Cooloff time, in minutes, for failed logins
- LOGIN_ATTEMPT_COOLOFF = config["general"]["login_attempt_cooloff"]
- # Maximum number of unsuccessful login attempts
- LOGIN_ATTEMPT_LIMIT = config["general"]["login_attempt_limit"]
- # Language code, e.g. en-gb
- LANGUAGE_CODE = config["general"]["language_code"]
- # Where `manage.py collectstatic` puts static files
- STATIC_ROOT = os.path.join(BASE_DIR, config["general"]["static_root"])
- # Email the server uses when sending emails
- SERVER_EMAIL = config["general"]["server_email"]
- # Site name used in page titles
- SITE_NAME = config["general"]["site_name"]
- # Link to source code
- SOURCE_LINK = config["general"]["source_link"]
- # Time zone
- TIME_ZONE = config["general"]["time_zone"]
- # Length of the local part (bit before the @) of autogenerated inbox addresses
- INBOX_LENGTH = config["inbox"]["inbox_length"]
- # Maximum number of free inboxes before a request for more will be generated
- MIN_INBOX_FOR_REQUEST = config["inbox"]["min_inbox_for_request"]
- # Increase the pool amount by this number when a user request is granted
- REQUEST_NUMBER = config["inbox"]["request_number"]
- # Where Celery looks for new tasks and stores results
- BROKER_URL = config["tasks"]["broker_url"]
- # Number of Celery processes to start
- CELERYD_CONCURRENCY = config["tasks"]["concurrency"]
- # Path where liberation data is temporarily stored
- LIBERATION_PATH = os.path.join(BASE_DIR, config["tasks"]["liberation"]["path"])
- # Databases!
- DATABASES = {
- 'default': {
- 'ENGINE': db_dict[config["database"]["engine"]],
- 'USER': config["database"]["user"],
- 'PASSWORD': config["database"]["password"],
- 'HOST': config["database"]["host"],
- 'PORT': config["database"]["port"],
- }
- }
- # "name" is a path for sqlite databases
- if config["database"]["engine"] == "sqlite":
- DATABASES["default"]["NAME"] = os.path.join(BASE_DIR, config["database"]["name"])
- else:
- DATABASES["default"]["NAME"] = config["database"]["name"]
- # Caches!
- CACHES = {
- 'default': {
- 'BACKEND': cache_dict[config["cache"]["backend"]],
- 'TIMEOUT': config["cache"]["timeout"],
- }
- }
- if config["cache"]["backend"] == "file":
- if config["cache"]["location"] == "":
- # sane default for minimum configuration
- CACHES["default"]["LOCATION"] = os.path.join(BASE_DIR, "inboxen_cache")
- else:
- CACHES["default"]["LOCATION"] = os.path.join(BASE_DIR, config["cache"]["location"])
- else:
- CACHES["default"]["LOCATION"] = config["cache"]["location"]
- # Hash used to store uniqueness of certain models
- # if you change this, you'll need to do a datamigration to change the rest
- COLUMN_HASHER = "sha1"
- ##
- # To override the following settings, create a separate settings module.
- # Import this module, override what you need to and set the environment
- # variable DJANGO_SETTINGS_MODULE to your module. See Django docs for details
- ##
- if not DEBUG:
- # These security settings are annoying while debugging
- CSRF_COOKIE_SECURE = True
- SESSION_COOKIE_SECURE = True
- ##
- # Celery options
- ##
- # load custom kombu encoder
- registry.register('json_date', jsondate.dumps, jsondate.loads,
- content_type='application/json+date', content_encoding='utf-8')
- CELERY_SEND_TASK_ERROR_EMAILS = True
- CELERY_RESULT_BACKEND = BROKER_URL
- CELERY_ACCEPT_CONTENT = ['json', 'json_date']
- CELERY_TASK_SERIALIZER = "json_date"
- CELERY_RESULT_SERIALIZER = "json_date"
- CELERY_QUEUES = (
- Queue('default', Exchange('default'), routing_key='default'),
- Broadcast('broadcast_tasks'),
- )
- CELERY_ROUTES = {'queue.tasks.force_garbage_collection': {'queue': 'broadcast_tasks'}}
- CELERY_DEFAULT_QUEUE = 'default'
- CELERY_DEFAULT_EXCHANGE = 'default'
- CELERY_DEFAULT_ROUTING_KEY = 'default'
- CELERYBEAT_SCHEDULE = {
- 'statistics': {
- 'task': 'queue.tasks.statistics',
- 'schedule': datetime.timedelta(days=1),
- },
- 'cleanup': {
- 'task': 'queue.delete.tasks.clean_orphan_models',
- 'schedule': datetime.timedelta(days=1),
- },
- 'requests': {
- 'task': 'queue.tasks.requests',
- 'schedule': datetime.timedelta(days=1),
- },
- }
- ##
- # Django options
- ##
- MESSAGE_TAGS = {message_constants.ERROR: 'danger'}
- SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
- TEMPLATE_DEBUG = DEBUG
- TEST_RUNNER = 'djcelery.contrib.test_runner.CeleryTestSuiteRunner'
- TWO_FACTOR_PATCH_ADMIN = False
- USE_I18N = True
- USE_L10N = True
- USE_TZ = True
- STATIC_URL = '/static/'
- STATICFILES_FINDERS = (
- 'django.contrib.staticfiles.finders.FileSystemFinder',
- 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
- )
- STATICFILES_STORAGE = 'inboxen.storage.ManifestStaticFilesStorage'
- AUTHENTICATION_BACKENDS = (
- 'website.backends.RateLimitWithSettings',
- )
- # Make sure all custom template tags are thread safe
- # https://docs.djangoproject.com/en/1.6/howto/custom-template-tags/#template-tag-thread-safety
- TEMPLATE_LOADERS = (
- ('django.template.loaders.cached.Loader', (
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader',
- )),
- )
- TEMPLATE_CONTEXT_PROCESSORS = (
- "django.contrib.auth.context_processors.auth",
- "django.core.context_processors.debug",
- "django.core.context_processors.i18n",
- "django.core.context_processors.static",
- "django.core.context_processors.tz",
- "django.core.context_processors.request",
- "django.contrib.messages.context_processors.messages",
- "website.context_processors.reduced_settings_context"
- )
- MIDDLEWARE_CLASSES = (
- 'django.middleware.common.CommonMiddleware',
- 'django.contrib.sessions.middleware.SessionMiddleware',
- 'django.middleware.csrf.CsrfViewMiddleware',
- 'django.middleware.locale.LocaleMiddleware',
- 'django.contrib.auth.middleware.AuthenticationMiddleware',
- 'django_otp.middleware.OTPMiddleware',
- 'django.contrib.messages.middleware.MessageMiddleware',
- 'async_messages.middleware.AsyncMiddleware',
- 'website.middleware.RateLimitMiddleware',
- 'django.middleware.clickjacking.XFrameOptionsMiddleware',
- )
- INSTALLED_APPS = (
- 'django.contrib.auth',
- 'django.contrib.contenttypes',
- 'django.contrib.sessions',
- 'django.contrib.messages',
- 'django.contrib.staticfiles',
- 'django.contrib.admin',
- 'bootstrapform',
- 'south',
- 'django_extensions',
- 'watson',
- 'djcelery',
- 'django_otp',
- 'django_otp.plugins.otp_static',
- 'django_otp.plugins.otp_totp',
- 'two_factor',
- 'inboxen',
- 'blog',
- 'website',
- 'queue',
- 'queue.delete',
- 'queue.liberate',
- 'tickets',
- 'termsofservice',
- )
- if DEBUG:
- INSTALLED_APPS += ('debug_toolbar',)
- ROOT_URLCONF = 'website.urls'
- LOGIN_URL = urlresolvers.reverse_lazy("user-login")
- LOGOUT_URL = urlresolvers.reverse_lazy("user-logout")
- LOGIN_REDIRECT_URL = urlresolvers.reverse_lazy("user-home")
- # Python dotted path to the WSGI application used by Django's runserver.
- WSGI_APPLICATION = 'website.wsgi.application'
- ##
- # Salmon. Splash.
- ##
- SALMON_SERVER = {"host": "localhost", "port": 8823, "type": "smtp"}
- ##
- # Misc.
- ##
- try:
- process = Popen("git rev-parse HEAD".split(), stdout=PIPE, close_fds=True, cwd=BASE_DIR)
- output = process.communicate()[0].strip()
- if not process.returncode:
- os.environ["INBOXEN_COMMIT_ID"] = output
- else:
- os.environ["INBOXEN_COMMIT_ID"] = "UNKNOWN"
- except OSError, TypeError:
- os.environ["INBOXEN_COMMIT_ID"] = "UNKNOWN"
|