diff --git a/WikiENS/settings/.gitignore b/WikiENS/settings/.gitignore deleted file mode 100644 index 2142506..0000000 --- a/WikiENS/settings/.gitignore +++ /dev/null @@ -1 +0,0 @@ -secret.py diff --git a/app/settings.py b/app/settings.py index e69de29..2fe02b0 100644 --- a/app/settings.py +++ b/app/settings.py @@ -0,0 +1,245 @@ +""" +Django settings for the wiki_ens project +""" + +from pathlib import Path + +from django.contrib.messages import constants as messages +from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ +from loadcredential import Credentials + +credentials = Credentials(env_prefix="WIKIENS_") + +# Build paths inside the project like this: BASE_DIR / 'subdir'. +BASE_DIR = Path(__file__).resolve().parent.parent + +# WARNING: keep the secret key used in production secret! +SECRET_KEY = credentials["SECRET_KEY"] + +# WARNING: don't run with debug turned on in production! +DEBUG = credentials.get_json("DEBUG", False) + +ALLOWED_HOSTS = credentials.get_json("ALLOWED_HOSTS", []) + +ADMINS = credentials.get_json("ADMINS", []) + + +### +# List the installed applications + +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_groups", + "wiki", + "wiki.plugins.attachments", + "wiki.plugins.notifications", + "wiki.plugins.images", + "wiki.plugins.macros", + "allauth_ens", + "allauth", + "allauth.account", + "allauth.socialaccount", + "allauth_ens.providers.clipper", +] + + +### +# List the installed middlewares + +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", +] + + +### +# The main url configuration + +ROOT_URLCONF = "app.urls" + + +### +# Template configuration: +# - Django Templating Language is used +# - Application directories can be used + + +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", + ], + }, + }, +] + + +### +# Database configuration +# -> https://docs.djangoproject.com/en/4.2/ref/settings/#databases + +DEFAULT_AUTO_FIELD = "django.db.models.AutoField" + +DATABASES = credentials.get_json( + "DATABASES", + { + "default": { + "ENGINE": "django.db.backends.sqlite3", + "NAME": BASE_DIR / "db.sqlite3", + } + }, +) + +CACHES = credentials.get_json( + "CACHES", + default={ + "default": { + "BACKEND": "django.core.cache.backends.locmem.LocMemCache", + }, + }, +) + + +### +# WSGI application configuration + +WSGI_APPLICATION = "app.wsgi.application" + + +### +# Staticfiles configuration + +STATIC_ROOT = credentials["STATIC_ROOT"] +STATIC_URL = "/static/" + +MEDIA_ROOT = credentials.get("MEDIA_ROOT", BASE_DIR / "media") +MEDIA_URL = "/media/" + + +### +# Internationalization configuration +# -> https://docs.djangoproject.com/en/4.2/topics/i18n/ + +LANGUAGE_CODE = "fr-fr" +TIME_ZONE = "Europe/Paris" + +USE_I18N = True +USE_L10N = True +USE_TZ = True + +LANGUAGES = [ + ("fr", _("Français")), +] + + +### +# Authentication configuration + +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/" +LOGOUT_URL = reverse_lazy("account_logout") +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 + +SOCIALACCOUNT_PROVIDERS = { + "clipper": { + "MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT": True, + "MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT_LEVEL": messages.INFO, + }, +} + +AUTH_PASSWORD_VALIDATORS = [ + {"NAME": f"django.contrib.auth.password_validation.{v}"} + for v in [ + "UserAttributeSimilarityValidator", + "MinimumLengthValidator", + "CommonPasswordValidator", + "NumericPasswordValidator", + ] +] + +### +# Wiki configuration + +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 + +# 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 + + +# FIXME: Add correct email settings + +# Development settings +if DEBUG: + EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" diff --git a/app/settings/__init__.py b/app/settings/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/app/settings/common.py b/app/settings/common.py deleted file mode 100644 index 5e78470..0000000 --- a/app/settings/common.py +++ /dev/null @@ -1,229 +0,0 @@ -import os - -from django.urls import reverse_lazy - -from django.contrib.messages import constants as messages - -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 -EMAIL_HOST = import_secret("EMAIL_HOST") - -DBNAME = import_secret("DBNAME") -DBUSER = import_secret("DBUSER") -DBPASSWD = import_secret("DBPASSWD") - -SERVER_EMAIL = "wiki@www.eleves.ens.fr" - -BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) - - -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_groups", - "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": "", - } -} - -DEFAULT_AUTO_FIELD = "django.db.models.AutoField" - -# 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/" -LOGOUT_URL = reverse_lazy("account_logout") -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 - -SOCIALACCOUNT_PROVIDERS = { - "clipper": { - "MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT": True, - "MESSAGE_SUGGEST_LOGOUT_ON_LOGOUT_LEVEL": messages.INFO, - }, -} - - -# 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/app/settings/local.py b/app/settings/local.py deleted file mode 100644 index 6771ca2..0000000 --- a/app/settings/local.py +++ /dev/null @@ -1,16 +0,0 @@ -import os - - -from .common import * # noqa -from .common import BASE_DIR - - -EMAIL_BACKEND = "django.core.mail.backends.console.EmailBackend" -DEBUG = True - -DATABASES = { - "default": { - "ENGINE": "django.db.backends.sqlite3", - "NAME": os.path.join(BASE_DIR, "db.sqlite3"), - } -} diff --git a/app/settings/prod.py b/app/settings/prod.py deleted file mode 100644 index 1c420b6..0000000 --- a/app/settings/prod.py +++ /dev/null @@ -1,11 +0,0 @@ -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/app/settings/secret_example.py b/app/settings/secret_example.py deleted file mode 100644 index 499f35d..0000000 --- a/app/settings/secret_example.py +++ /dev/null @@ -1,7 +0,0 @@ -SECRET_KEY = "_u5q4-^1qgkqg=i5o5ha*xkd@82#l$e+%m)$v+4y#t-5!g-%g2" -ADMINS = None -EMAIL_HOST = "localhost" - -DBNAME = "wiki" -DBUSER = "wiki" -DBPASSWD = "dummy" diff --git a/app/urls.py b/app/urls.py index 4c378cc..3060432 100644 --- a/app/urls.py +++ b/app/urls.py @@ -1,22 +1,20 @@ from allauth_ens.views import capture_login, capture_logout -from django.conf.urls import include, url from django.contrib import admin -from django_nyt.urls import get_pattern as get_nyt_pattern -from wiki.urls import get_pattern as get_wiki_pattern +from django.urls import include, path allauth_urls = [ # Catch login/logout views of admin site. - url(r"^_admin/login/$", capture_login), - url(r"^_admin/logout/$", capture_logout), + path("admin/login/", capture_login), + path("admin/logout/", capture_logout), # Allauth urls. - url(r"^_profil/", include("allauth.urls")), + path("profil/", include("allauth.urls")), ] urlpatterns = allauth_urls + [ - url(r"^_admin/", admin.site.urls), - url(r"^notifications/", get_nyt_pattern()), - url(r"^_groups/", include("wiki_groups.urls")), - url(r"", get_wiki_pattern()), + path("_admin/", admin.site.urls), + path("notifications/", include("django_nyt.urls")), + path("_groups/", include("wiki_groups.urls")), + path("", include("wiki.urls")), ] # TODO add MEDIA_ROOT diff --git a/wiki_groups/__init__.py b/wiki_groups/__init__.py index 8588003..e69de29 100644 --- a/wiki_groups/__init__.py +++ b/wiki_groups/__init__.py @@ -1 +0,0 @@ -default_app_config = "wiki_groups.apps.WikiGroupsConfig"