mirror of
https://github.com/freedombox/FreedomBox.git
synced 2026-01-21 07:55:00 +00:00
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org> Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
146 lines
4.6 KiB
Python
146 lines
4.6 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
"""
|
|
Setup Django web framework.
|
|
"""
|
|
|
|
import logging
|
|
import os
|
|
import pathlib
|
|
import random
|
|
import stat
|
|
|
|
import django.conf
|
|
import django.core.management
|
|
import django.core.wsgi
|
|
from django.conf import global_settings
|
|
from django.contrib.messages import constants as message_constants
|
|
|
|
from . import cfg, glib, log, module_loader, settings
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def init(read_only=False):
|
|
"""Setup Django configuration in the absence of .settings file"""
|
|
# Workaround for django-simple-captcha 0.5.6 not being compatible with
|
|
# Django 3.2. 0.5.14 is almost there in Debian. Workaround only until then.
|
|
django.utils.encoding.python_2_unicode_compatible = lambda x: x
|
|
|
|
if cfg.secure_proxy_ssl_header:
|
|
settings.SECURE_PROXY_SSL_HEADER = (cfg.secure_proxy_ssl_header,
|
|
'https')
|
|
|
|
if cfg.use_x_forwarded_for:
|
|
settings.IPWARE_META_PRECEDENCE_ORDER = ('HTTP_X_FORWARDED_FOR', )
|
|
|
|
settings.DATABASES['default']['NAME'] = cfg.store_file
|
|
settings.DEBUG = cfg.develop
|
|
settings.FORCE_SCRIPT_NAME = cfg.server_dir
|
|
settings.INSTALLED_APPS += module_loader.get_modules_to_load()
|
|
settings.LANGUAGES = get_languages()
|
|
settings.LOGGING = log.get_configuration()
|
|
settings.MESSAGE_TAGS = {message_constants.ERROR: 'danger'}
|
|
settings.SECRET_KEY = _get_secret_key(read_only)
|
|
settings.SESSION_FILE_PATH = os.path.join(cfg.data_dir, 'sessions')
|
|
settings.STATIC_URL = '/'.join([cfg.server_dir,
|
|
'static/']).replace('//', '/')
|
|
settings.USE_X_FORWARDED_HOST = cfg.use_x_forwarded_host
|
|
|
|
kwargs = {}
|
|
for setting in dir(settings):
|
|
if setting.isupper():
|
|
kwargs[setting] = getattr(settings, setting)
|
|
|
|
django.conf.settings.configure(**kwargs)
|
|
django.setup(set_prefix=True)
|
|
|
|
logger.debug('Configured Django with applications - %s',
|
|
', '.join(settings.INSTALLED_APPS))
|
|
|
|
|
|
def post_init():
|
|
"""Perform operations after completing init of other modules."""
|
|
logger.debug('Creating or adding new tables to data file')
|
|
django.core.management.call_command('migrate', '--fake-initial',
|
|
interactive=False, verbosity=0)
|
|
os.chmod(cfg.store_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
|
|
|
|
# Cleanup expired sessions every day
|
|
glib.schedule(24 * 3600, _cleanup_expired_sessions, in_thread=True)
|
|
|
|
|
|
def _get_secret_key(read_only=False):
|
|
"""Retrieve or create a new Django secret key."""
|
|
secret_key_file = pathlib.Path(cfg.data_dir) / 'django-secret.key'
|
|
if secret_key_file.exists():
|
|
secret_key = secret_key_file.read_text()
|
|
if len(secret_key) >= 128:
|
|
return secret_key
|
|
|
|
if read_only:
|
|
return ''
|
|
|
|
secret_key = _generate_secret_key()
|
|
# File should be created with permission 0o700
|
|
old_umask = os.umask(0o077)
|
|
try:
|
|
secret_key_file.write_text(secret_key)
|
|
finally:
|
|
os.umask(old_umask)
|
|
|
|
return secret_key
|
|
|
|
|
|
def _generate_secret_key():
|
|
"""Generate a new random secret key for use with Django."""
|
|
# We could have used django.core.management.utils.get_random_secret_key
|
|
# but it is not documented and should be considered private.
|
|
length = 128
|
|
chars = 'abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)'
|
|
rand = random.SystemRandom()
|
|
return ''.join(rand.choice(chars) for _ in range(length))
|
|
|
|
|
|
def get_languages():
|
|
"""Return list of languages to show in the interface.
|
|
|
|
Add additional languages that FreedomBox support but Django doesn't.
|
|
|
|
"""
|
|
|
|
def gettext_noop(string):
|
|
"""Django's actual translation methods need Django to be setup."""
|
|
return string
|
|
|
|
return sorted(
|
|
list(global_settings.LANGUAGES) + [
|
|
('gu', gettext_noop('Gujarati')),
|
|
])
|
|
|
|
|
|
def _cleanup_expired_sessions(data):
|
|
"""Cleanup expired Django sessions."""
|
|
verbosity = 1 if cfg.develop else 0
|
|
django.core.management.call_command('clearsessions', verbosity=verbosity)
|
|
|
|
|
|
def get_wsgi_application():
|
|
"""Return Django wsgi application."""
|
|
return django.core.wsgi.get_wsgi_application()
|
|
|
|
|
|
def get_static_url():
|
|
"""Return Django static URL."""
|
|
return django.conf.settings.STATIC_URL
|
|
|
|
|
|
def get_ip_address_from_request(request):
|
|
"""Return the IP address of the original client."""
|
|
if cfg.use_x_forwarded_for:
|
|
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
|
ip_address = x_forwarded_for.split(',')[0]
|
|
else:
|
|
ip_address = request.META.get('REMOTE_ADDR')
|
|
|
|
return ip_address
|