From ae082bc9fb9b93cd1edafe23477cfad21c6dbf87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Sun, 7 Oct 2018 18:24:57 +0200 Subject: [PATCH] Split production / development settings --- WikiENS/settings/.gitignore | 1 + WikiENS/settings/common.py | 219 +++++++++++++++++++++++++++++ WikiENS/settings/local.py | 20 +++ WikiENS/settings/prod.py | 11 ++ WikiENS/settings/secret_example.py | 8 ++ manage.py | 2 +- 6 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 WikiENS/settings/.gitignore create mode 100644 WikiENS/settings/common.py create mode 100644 WikiENS/settings/local.py create mode 100644 WikiENS/settings/prod.py create mode 100644 WikiENS/settings/secret_example.py diff --git a/WikiENS/settings/.gitignore b/WikiENS/settings/.gitignore new file mode 100644 index 0000000..2142506 --- /dev/null +++ b/WikiENS/settings/.gitignore @@ -0,0 +1 @@ +secret.py diff --git a/WikiENS/settings/common.py b/WikiENS/settings/common.py new file mode 100644 index 0000000..e64923c --- /dev/null +++ b/WikiENS/settings/common.py @@ -0,0 +1,219 @@ +import os +import sys + +from django.core.urlresolvers import reverse_lazy + +try: + from . import secret +except ImportError: + raise ImportError( + "The secret.py file is missing.\n" + "For a development environment, simply copy secret_example.py" + ) + + +def import_secret(name): + """ + Shorthand for importing a value from the secret module and raising an + informative exception if a secret is missing. + """ + try: + return getattr(secret, name) + except AttributeError: + raise RuntimeError("Secret missing: {}".format(name)) + + +SECRET_KEY = import_secret("SECRET_KEY") +ADMINS = import_secret("ADMINS") +MANAGERS = ADMINS +SERVER_EMAIL = import_secret("SERVER_EMAIL") +EMAIL_HOST = import_secret("EMAIL_HOST") + +DBNAME = import_secret("DBNAME") +DBUSER = import_secret("DBUSER") +DBPASSWD = import_secret("DBPASSWD") + + +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +TESTING = sys.argv[1] == "test" + + +INSTALLED_APPS = [ + "django.contrib.admin", + "django.contrib.auth", + "django.contrib.contenttypes", + "django.contrib.sessions", + "django.contrib.messages", + "django.contrib.staticfiles", + "django.contrib.sites", + "django.contrib.humanize", + "django_nyt", + "mptt", + "sekizai", + "sorl.thumbnail", + "widget_tweaks", + "shared", # Keep `shared` above `wiki` to override the default templates + "wiki", + "wiki.plugins.attachments", + "wiki.plugins.notifications", + "wiki.plugins.images", + "wiki.plugins.macros", + "allauth_ens", + "allauth", + "allauth.account", + "allauth.socialaccount", + "allauth_ens.providers.clipper", +] + +MIDDLEWARE = [ + "django.middleware.security.SecurityMiddleware", + "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", +] + +ROOT_URLCONF = "WikiENS.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", + "sekizai.context_processors.sekizai", + ] + }, + } +] + +WSGI_APPLICATION = "WikiENS.wsgi.application" + +SITE_ID = 1 + + +# Database +# https://docs.djangoproject.com/en/1.11/ref/settings/#databases + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.postgresql", + "NAME": DBNAME, + "USER": DBUSER, + "PASSWORD": DBPASSWD, + "HOST": "localhost", + } +} + + +# Password validation +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + "NAME": ( + # XXX. Cette chaîne est très longue… Je la coupe en deux sinon + # black ne me fiche pas la paix (mais c'est vraiment nul) + "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/1.11/topics/i18n/ + +LANGUAGE_CODE = "fr-fr" + +TIME_ZONE = "Europe/Paris" + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Authentication +# https://docs.djangoproject.com/en/1.11/ref/settings/#auth +# https://django-allauth.readthedocs.io/en/latest/index.html + +AUTHENTICATION_BACKENDS = [ + "allauth.account.auth_backends.AuthenticationBackend", +] + +ACCOUNT_ADAPTER = "shared.allauth_adapter.AccountAdapter" +SOCIALACCOUNT_ADAPTER = "shared.allauth_adapter.SocialAccountAdapter" + +HOME_URL = reverse_lazy("wiki:root") + +LOGIN_URL = "/_profil/login/" +LOGIN_REDIRECT_URL = HOME_URL +ACCOUNT_LOGOUT_REDIRECT_URL = HOME_URL + + +def user_display(user): + return user.get_full_name() or user.username + + +ACCOUNT_AUTHENTICATED_LOGIN_REDIRECTS = False +ACCOUNT_HOME_URL = HOME_URL +ACCOUNT_USER_DISPLAY = user_display + + +# Static / media contents + +STATIC_URL = "/_static/" +MEDIA_URL = "/_media/" + + +# WIKI SETTINGS + +WIKI_ATTACHMENTS_EXTENSIONS = [ + "pdf", + "doc", + "odt", + "docx", + "txt", + "md", + "c2p", + "msc", + "png", + "jpg", + "svg", + "ai", + "esf", + "tex", +] + +WIKI_REVISIONS_PER_HOUR = 180 +WIKI_REVISIONS_PER_MINUTES = 180 + +# Dark magic - tell django to use X-Forwarded-* +# This is needed for django-allauth-cas, see +# https://blog.ubuntu.com/2015/08/18/django-behind-a-proxy-fixing-absolute-urls +USE_X_FORWARDED_HOST = True +SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') + +# Use sign up, login, logout, profile settings views of allauth. +WIKI_ACCOUNT_HANDLING = False + +# Signup allowed? If it’s not allowed, logged in superusers +# can still access the signup page to create new users. +WIKI_ACCOUNT_SIGNUP_ALLOWED = True + +# Globally enable write access for anonymous users, if true anonymous users +# will be treated as the others_write boolean field on models.Article. +WIKI_ANONYMOUS_WRITE = False +WIKI_ANONYMOUS = False diff --git a/WikiENS/settings/local.py b/WikiENS/settings/local.py new file mode 100644 index 0000000..81b7e8f --- /dev/null +++ b/WikiENS/settings/local.py @@ -0,0 +1,20 @@ +import os + + +from .common import * # noqa +from .common import TESTING, BASE_DIR + + +EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" +DEBUG = True + +if TESTING: + PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] + + +DATABASES = { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": os.path.join(BASE_DIR, "db.sqlite3") + } +} diff --git a/WikiENS/settings/prod.py b/WikiENS/settings/prod.py new file mode 100644 index 0000000..1c420b6 --- /dev/null +++ b/WikiENS/settings/prod.py @@ -0,0 +1,11 @@ +import os + +from .common import * # noqa +from .common import BASE_DIR + + +DEBUG = False +ALLOWED_HOSTS = ["www.eleves.ens.fr", "wiki.eleves.ens.fr"] + +STATIC_ROOT = os.path.join(BASE_DIR, "..", "static") +MEDIA_ROOT = os.path.join(BASE_DIR, "..", "media") diff --git a/WikiENS/settings/secret_example.py b/WikiENS/settings/secret_example.py new file mode 100644 index 0000000..6d77f47 --- /dev/null +++ b/WikiENS/settings/secret_example.py @@ -0,0 +1,8 @@ +SECRET_KEY = '_u5q4-^1qgkqg=i5o5ha*xkd@82#l$e+%m)$v+4y#t-5!g-%g2' +ADMINS = None +SERVER_EMAIL = "changeme@localhost" +EMAIL_HOST = "localhost" + +DBNAME = "wiki" +DBUSER = "wiki" +DBPASSWD = "dummy" diff --git a/manage.py b/manage.py index 1ae7a2c..bd7b5ad 100755 --- a/manage.py +++ b/manage.py @@ -3,7 +3,7 @@ import os import sys if __name__ == "__main__": - os.environ.setdefault("DJANGO_SETTINGS_MODULE", "WikiENS.settings") + os.environ.setdefault("DJANGO_SETTINGS_MODULE", "WikiENS.settings.local") try: from django.core.management import execute_from_command_line except ImportError: