separate passbook.core into passbook.root and passbook.core

Move Main Django Project into passbook.root while passbook.core holds core functionality.

passbook.root contains main settings, ASGI & WSGI, celery and URLs.
This commit is contained in:
Jens Langhammer
2019-06-25 18:00:54 +02:00
parent 3b2c2d781f
commit a798412e17
16 changed files with 69 additions and 50 deletions

View File

@ -14,6 +14,7 @@ class PassbookCoreConfig(AppConfig):
name = 'passbook.core'
label = 'passbook_core'
verbose_name = 'passbook Core'
mountpoint = ''
def ready(self):
import_module('passbook.core.policies')

View File

@ -1,13 +0,0 @@
"""
ASGI entrypoint. Configures Django and then runs the application
defined in the ASGI_APPLICATION setting.
"""
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passbook.core.settings")
django.setup()
application = get_default_application()

View File

@ -1,55 +0,0 @@
"""passbook core celery"""
import logging
import os
from celery import Celery, signals
from django.conf import settings
# set the default Django settings module for the 'celery' program.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "passbook.core.settings")
LOGGER = logging.getLogger(__name__)
CELERY_APP = Celery('passbook')
# pylint: disable=unused-argument
@signals.setup_logging.connect
def config_loggers(*args, **kwags):
"""Apply logging settings from settings.py to celery"""
logging.config.dictConfig(settings.LOGGING)
# pylint: disable=unused-argument
@signals.after_task_publish.connect
def after_task_publish(sender=None, headers=None, body=None, **kwargs):
"""Log task_id after it was published"""
info = headers if 'task' in headers else body
LOGGER.debug('%-40s published (name=%s)', info.get('id'), info.get('task'))
# pylint: disable=unused-argument
@signals.task_prerun.connect
def task_prerun(task_id, task, *args, **kwargs):
"""Log task_id on worker"""
LOGGER.debug('%-40s started (name=%s)', task_id, task.__name__)
# pylint: disable=unused-argument
@signals.task_postrun.connect
def task_postrun(task_id, task, *args, retval=None, state=None, **kwargs):
"""Log task_id on worker"""
LOGGER.debug('%-40s finished (name=%s, state=%s)',
task_id, task.__name__, state)
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
CELERY_APP.config_from_object(settings, namespace='CELERY')
# Load task modules from all registered Django app configs.
CELERY_APP.autodiscover_tasks()

View File

@ -26,5 +26,5 @@ class Command(BaseCommand):
'-b', CONFIG.y('web.listen', '0.0.0.0'), # nosec
'--access-log', '/dev/null',
'--application-close-timeout', '500',
'passbook.core.asgi:application'
'passbook.root.asgi:application'
])

View File

@ -5,7 +5,7 @@ from logging import getLogger
from django.core.management.base import BaseCommand
from django.utils import autoreload
from passbook.core.celery import CELERY_APP
from passbook.root.celery import CELERY_APP
LOGGER = getLogger(__name__)

View File

@ -7,8 +7,8 @@ from celery.exceptions import TimeoutError as CeleryTimeoutError
from django.core.cache import cache
from ipware import get_client_ip
from passbook.core.celery import CELERY_APP
from passbook.core.models import Policy, User
from passbook.root.celery import CELERY_APP
LOGGER = getLogger(__name__)

View File

@ -1,15 +0,0 @@
celery
colorlog
django-ipware
django-model-utils
django-redis
django>=2.0
djangorestframework
idna<2.8,>=2.5
markdown
psycopg2
PyYAML
sentry-sdk
pip
whitenoise
urllib3<1.25,>=1.21.1

View File

@ -1,366 +0,0 @@
"""
Django settings for passbook project.
Generated by 'django-admin startproject' using Django 2.1.3.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import importlib
import logging
import os
import sys
from celery.schedules import crontab
from django.contrib import messages
from sentry_sdk import init as sentry_init
from sentry_sdk.integrations.celery import CeleryIntegration
from sentry_sdk.integrations.django import DjangoIntegration
from sentry_sdk.integrations.logging import LoggingIntegration
from passbook import __version__
from passbook.lib.config import CONFIG
from passbook.lib.sentry import before_send
VERSION = __version__
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
STATIC_ROOT = BASE_DIR + '/static'
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = CONFIG.get('secret_key')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = CONFIG.get('debug')
INTERNAL_IPS = ['127.0.0.1']
# ALLOWED_HOSTS = CONFIG.get('domains', []) + [CONFIG.get('primary_domain')]
ALLOWED_HOSTS = ['*']
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
LOGIN_URL = 'passbook_core:auth-login'
# CSRF_FAILURE_VIEW = 'passbook.core.views.errors.CSRFErrorView.as_view'
# Custom user model
AUTH_USER_MODEL = 'passbook_core.User'
CSRF_COOKIE_NAME = 'passbook_csrf'
SESSION_COOKIE_NAME = 'passbook_session'
SESSION_COOKIE_DOMAIN = CONFIG.get('primary_domain')
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"
LANGUAGE_COOKIE_NAME = 'passbook_language'
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.postgres',
'rest_framework',
'drf_yasg',
'passbook.core.apps.PassbookCoreConfig',
'passbook.admin.apps.PassbookAdminConfig',
'passbook.api.apps.PassbookAPIConfig',
'passbook.audit.apps.PassbookAuditConfig',
'passbook.lib.apps.PassbookLibConfig',
'passbook.ldap.apps.PassbookLdapConfig',
'passbook.oauth_client.apps.PassbookOAuthClientConfig',
'passbook.oauth_provider.apps.PassbookOAuthProviderConfig',
'passbook.saml_idp.apps.PassbookSAMLIDPConfig',
'passbook.otp.apps.PassbookOTPConfig',
'passbook.captcha_factor.apps.PassbookCaptchaFactorConfig',
'passbook.hibp_policy.apps.PassbookHIBPConfig',
'passbook.pretend.apps.PassbookPretendConfig',
'passbook.password_expiry_policy.apps.PassbookPasswordExpiryPolicyConfig',
'passbook.suspicious_policy.apps.PassbookSuspiciousPolicyConfig',
'passbook.app_gw.apps.PassbookApplicationApplicationGatewayConfig',
]
# Message Tag fix for bootstrap CSS Classes
MESSAGE_TAGS = {
messages.DEBUG: 'primary',
messages.INFO: 'info',
messages.SUCCESS: 'success',
messages.WARNING: 'warning',
messages.ERROR: 'danger',
}
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://%s" % CONFIG.get('redis'),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
MIDDLEWARE = [
'django.contrib.sessions.middleware.SessionMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'passbook.app_gw.middleware.ApplicationGatewayMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'passbook.core.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 = 'passbook.core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {}
for db_alias, db_config in CONFIG.get('databases').items():
DATABASES[db_alias] = {
'ENGINE': db_config.get('engine'),
'HOST': db_config.get('host'),
'NAME': db_config.get('name'),
'USER': db_config.get('user'),
'PASSWORD': db_config.get('password'),
'OPTIONS': db_config.get('options', {}),
}
# Password validation
# https://docs.djangoproject.com/en/2.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/2.1/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Celery settings
# Add a 10 minute timeout to all Celery tasks.
CELERY_TASK_SOFT_TIME_LIMIT = 600
CELERY_TIMEZONE = TIME_ZONE
CELERY_BEAT_SCHEDULE = {}
CELERY_CREATE_MISSING_QUEUES = True
CELERY_TASK_DEFAULT_QUEUE = 'passbook'
CELERY_BROKER_URL = 'amqp://%s' % CONFIG.get('rabbitmq')
CELERY_RESULT_BACKEND = 'rpc://'
CELERY_ACKS_LATE = True
CELERY_BROKER_HEARTBEAT = 0
CELERY_BEAT_SCHEDULE = {
'cleanup-expired-nonces': {
'task': 'passbook.core.tasks.clean_nonces',
'schedule': crontab(hour=1, minute=1)
}
}
if not DEBUG:
sentry_init(
dsn="https://55b5dd780bc14f4c96bba69b7a9abbcc@sentry.services.beryju.org/8",
integrations=[
DjangoIntegration(),
CeleryIntegration(),
LoggingIntegration(
level=logging.INFO,
event_level=logging.ERROR
)
],
send_default_pii=True,
before_send=before_send,
release='p2@%s' % __version__
)
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
with CONFIG.cd('log'):
LOGGING = {
'version': 1,
'disable_existing_loggers': True,
'formatters': {
'verbose': {
'format': ('%(asctime)s %(levelname)-8s %(name)-55s '
'%(funcName)-20s %(message)s'),
},
'color': {
'()': 'colorlog.ColoredFormatter',
'format': ('%(log_color)s%(asctime)s %(levelname)-8s %(name)-55s '
'%(funcName)-20s %(message)s'),
'log_colors': {
'DEBUG': 'bold_black',
'INFO': 'white',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'bold_red',
'SUCCESS': 'green',
},
}
},
'handlers': {
'console': {
'level': CONFIG.get('level').get('console'),
'class': 'logging.StreamHandler',
'formatter': 'color',
},
'syslog': {
'level': CONFIG.get('level').get('file'),
'class': 'logging.handlers.SysLogHandler',
'formatter': 'verbose',
'address': (CONFIG.get('syslog').get('host'),
CONFIG.get('syslog').get('port'))
},
'file': {
'level': CONFIG.get('level').get('file'),
'class': 'logging.FileHandler',
'formatter': 'verbose',
'filename': CONFIG.get('file'),
},
'queue': {
'level': CONFIG.get('level').get('console'),
'class': 'passbook.lib.log.QueueListenerHandler',
'handlers': [
'cfg://handlers.console',
# 'cfg://handlers.syslog',
'cfg://handlers.file',
],
}
},
'loggers': {
'passbook': {
'handlers': ['queue'],
'level': 'DEBUG',
'propagate': True,
},
'django': {
'handlers': ['queue'],
'level': 'INFO',
'propagate': True,
},
'tasks': {
'handlers': ['queue'],
'level': 'DEBUG',
'propagate': True,
},
'cherrypy': {
'handlers': ['queue'],
'level': 'DEBUG',
'propagate': True,
},
'oauthlib': {
'handlers': ['queue'],
'level': 'DEBUG',
'propagate': True,
},
'oauth2_provider': {
'handlers': ['queue'],
'level': 'DEBUG',
'propagate': True,
},
'daphne': {
'handlers': ['queue'],
'level': 'INFO',
'propagate': True,
}
}
}
TEST = False
TEST_RUNNER = 'xmlrunner.extra.djangotestrunner.XMLTestRunner'
TEST_OUTPUT_VERBOSE = 2
TEST_OUTPUT_FILE_NAME = 'unittest.xml'
if any('test' in arg for arg in sys.argv):
LOGGING = None
TEST = True
CELERY_TASK_ALWAYS_EAGER = True
_DISALLOWED_ITEMS = ['INSTALLED_APPS', 'MIDDLEWARE', 'AUTHENTICATION_BACKENDS']
# Load subapps's INSTALLED_APPS
for _app in INSTALLED_APPS:
if _app.startswith('passbook') and \
not _app.startswith('passbook.core'):
if 'apps' in _app:
_app = '.'.join(_app.split('.')[:-2])
try:
app_settings = importlib.import_module("%s.settings" % _app)
INSTALLED_APPS.extend(getattr(app_settings, 'INSTALLED_APPS', []))
MIDDLEWARE.extend(getattr(app_settings, 'MIDDLEWARE', []))
AUTHENTICATION_BACKENDS.extend(getattr(app_settings, 'AUTHENTICATION_BACKENDS', []))
for _attr in dir(app_settings):
if not _attr.startswith('__') and _attr not in _DISALLOWED_ITEMS:
globals()[_attr] = getattr(app_settings, _attr)
except ImportError:
pass
if DEBUG:
INSTALLED_APPS.append('debug_toolbar')
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')

View File

@ -6,9 +6,9 @@ from django.core.mail import EmailMultiAlternatives
from django.template.loader import render_to_string
from django.utils.html import strip_tags
from passbook.core.celery import CELERY_APP
from passbook.core.models import Nonce
from passbook.lib.config import CONFIG
from passbook.root.celery import CELERY_APP
LOGGER = getLogger(__name__)

View File

@ -1,25 +1,14 @@
"""passbook URL Configuration"""
from logging import getLogger
from django.conf import settings
from django.contrib import admin
from django.urls import include, path
from django.views.generic import RedirectView
from django.urls import path
from passbook.core.auth import view
from passbook.core.views import authentication, error, overview, user
from passbook.lib.utils.reflection import get_apps
from passbook.core.views import authentication, overview, user
LOGGER = getLogger(__name__)
admin.autodiscover()
admin.site.login = RedirectView.as_view(pattern_name='passbook_core:auth-login')
handler400 = error.BadRequestView.as_view()
handler403 = error.ForbiddenView.as_view()
handler404 = error.NotFoundView.as_view()
handler500 = error.ServerErrorView.as_view()
core_urls = [
urlpatterns = [
# Authentication views
path('auth/login/', authentication.LoginView.as_view(), name='auth-login'),
path('auth/logout/', authentication.LogoutView.as_view(), name='auth-logout'),
@ -39,27 +28,3 @@ core_urls = [
# Overview
path('', overview.OverviewView.as_view(), name='overview'),
]
urlpatterns = [
# Core (include our own URLs so namespaces are used everywhere)
path('', include((core_urls, 'passbook_core'), namespace='passbook_core')),
]
for _passbook_app in get_apps():
if hasattr(_passbook_app, 'mountpoint'):
_path = path(_passbook_app.mountpoint, include((_passbook_app.name+'.urls',
_passbook_app.label),
namespace=_passbook_app.label))
urlpatterns.append(_path)
LOGGER.debug("Loaded %s's URLs", _passbook_app.name)
urlpatterns += [
# Administration
path('administration/django/', admin.site.urls),
]
if settings.DEBUG:
import debug_toolbar
urlpatterns = [
path('__debug__/', include(debug_toolbar.urls)),
] + urlpatterns

View File

@ -1,17 +0,0 @@
"""
WSGI config for passbook project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
from sentry_sdk.integrations.wsgi import SentryWsgiMiddleware
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'passbook.settings')
application = SentryWsgiMiddleware(get_wsgi_application())