FreedomBox/plinth.py
Sunil Mohan Adapa 65cdcb1bc3 Re-introduce Django CSRF middleware
It is a security issue not to include the Django CSRF middle. Also, since we
don't have a reason to alter the Django middleware list and order, we should
use the same list.
2014-08-17 19:29:31 +05:30

225 lines
7.0 KiB
Python
Executable File

#!/usr/bin/env python
import argparse
import django.conf
import django.core.management
import django.core.wsgi
import logging
import os
import stat
import sys
import cherrypy
from cherrypy import _cpserver
from cherrypy.process.plugins import Daemonizer
import cfg
import module_loader
import service
__version__ = "0.2.14"
__author__ = "James Vasile"
__copyright__ = "Copyright 2011-2013, James Vasile"
__license__ = "GPLv3 or later"
__maintainer__ = "James Vasile"
__email__ = "james@jamesvasile.com"
__status__ = "Development"
LOGGER = logging.getLogger(__name__)
def parse_arguments():
"""Parse command line arguments"""
parser = argparse.ArgumentParser(
description='Plinth web interface for FreedomBox')
parser.add_argument(
'--pidfile', default='plinth.pid',
help='specify a file in which the server may write its pid')
# TODO: server_dir is actually a url prefix; use a better variable name
parser.add_argument(
'--server_dir', default='/',
help='web server path under which to serve')
parser.add_argument(
'--debug', action='store_true', default=False,
help='enable debugging and run server *insecurely*')
parser.add_argument(
'--no-daemon', action='store_true', default=False,
help='do not start as a daemon')
args = parser.parse_args()
cfg.pidfile = args.pidfile
cfg.server_dir = args.server_dir
cfg.debug = args.debug
cfg.no_daemon = args.no_daemon
def setup_logging():
"""Setup logging framework"""
# Don't propagate cherrypy log messages to root logger
logging.getLogger('cherrypy').propagate = False
cherrypy.log.error_file = cfg.status_log_file
cherrypy.log.access_file = cfg.access_log_file
if not cfg.no_daemon:
cherrypy.log.screen = False
def setup_paths():
"""Setup current directory and python import paths"""
os.chdir(cfg.python_root)
if not os.path.join(cfg.file_root, 'vendor') in sys.path:
sys.path.append(os.path.join(cfg.file_root, 'vendor'))
def setup_server():
"""Setup CherryPy server"""
LOGGER.info('Setting up CherryPy server')
# Set the PID file path
try:
if cfg.pidfile:
from cherrypy.process.plugins import PIDFile
PIDFile(cherrypy.engine, cfg.pidfile).subscribe()
except AttributeError:
pass
# Add an extra server
server = _cpserver.Server()
server.socket_host = '127.0.0.1'
server.socket_port = 52854
server.subscribe()
# Configure default server
cherrypy.config.update(
{'server.socket_host': cfg.host,
'server.socket_port': cfg.port,
'server.thread_pool': 10})
application = django.core.wsgi.get_wsgi_application()
cherrypy.tree.graft(application, cfg.server_dir)
config = {
'/': {'tools.staticdir.root': '%s/static' % cfg.file_root,
'tools.staticdir.on': True,
'tools.staticdir.dir': '.'}}
cherrypy.tree.mount(None, django.conf.settings.STATIC_URL, config)
if not cfg.no_daemon:
Daemonizer(cherrypy.engine).subscribe()
cherrypy.engine.signal_handler.subscribe()
def configure_django():
"""Setup Django configuration in the absense of .settings file"""
# In module_loader.py we reverse URLs for the menu before having a proper
# request. In this case, get_script_prefix (used by reverse) returns the
# wrong prefix. Set it here manually to have the correct prefix right away.
django.core.urlresolvers.set_script_prefix(cfg.server_dir)
context_processors = [
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages',
'context_processors.plinth_processor']
logging_configuration = {
'version': 1,
'disable_existing_loggers': False,
'formatters': {
'default': {
'format':
'[%(asctime)s] %(name)-14s %(levelname)-8s %(message)s',
}
},
'handlers': {
'file': {
'class': 'logging.FileHandler',
'filename': cfg.status_log_file,
'formatter': 'default'
},
'console': {
'class': 'logging.StreamHandler',
'formatter': 'default'
}
},
'root': {
'handlers': ['console', 'file'],
'level': 'DEBUG' if cfg.debug else 'INFO'
}
}
data_file = os.path.join(cfg.data_dir, 'plinth.sqlite3')
template_directories = module_loader.get_template_directories()
sessions_directory = os.path.join(cfg.data_dir, 'sessions')
django.conf.settings.configure(
ALLOWED_HOSTS=['127.0.0.1', 'localhost'],
CACHES={'default':
{'BACKEND': 'django.core.cache.backends.dummy.DummyCache'}},
DATABASES={'default':
{'ENGINE': 'django.db.backends.sqlite3',
'NAME': data_file}},
DEBUG=cfg.debug,
INSTALLED_APPS=['bootstrapform',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.messages'],
LOGGING=logging_configuration,
LOGIN_URL='lib:login',
LOGIN_REDIRECT_URL='apps:index',
LOGOUT_URL='lib:logout',
MIDDLEWARE_CLASSES=(
'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',
'modules.first_boot.middleware.FirstBootMiddleware',
),
ROOT_URLCONF='urls',
SESSION_ENGINE='django.contrib.sessions.backends.file',
SESSION_FILE_PATH=sessions_directory,
STATIC_URL=os.path.join(cfg.server_dir, 'static/'),
TEMPLATE_CONTEXT_PROCESSORS=context_processors,
TEMPLATE_DIRS=template_directories)
LOGGER.info('Configured Django')
LOGGER.info('Template directories - %s', template_directories)
if not os.path.isfile(data_file):
LOGGER.info('Creating and initializing data file')
django.core.management.call_command('syncdb', interactive=False)
os.chmod(data_file, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP)
def main():
"""Intialize and start the application"""
parse_arguments()
cfg.read()
setup_logging()
service.init()
setup_paths()
configure_django()
module_loader.load_modules()
setup_server()
cherrypy.engine.start()
cherrypy.engine.block()
if __name__ == '__main__':
main()