From 5e201b44fbae2c6c3587c5f86dc2e3bfe186e763 Mon Sep 17 00:00:00 2001 From: Yohan Boniface Date: Mon, 5 Jun 2023 11:48:21 +0200 Subject: [PATCH] Use django-environ to make part of the settings available throught env vars --- Dockerfile | 1 - setup.cfg | 1 + umap/settings/__init__.py | 53 +++++++------ umap/settings/base.py | 60 ++++++++++++--- umap/settings/docker.py | 155 -------------------------------------- 5 files changed, 75 insertions(+), 195 deletions(-) delete mode 100644 umap/settings/docker.py diff --git a/Dockerfile b/Dockerfile index e8a523cf..02926cbf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,7 +11,6 @@ RUN make vendors FROM python:3.8-slim ENV PYTHONUNBUFFERED=1 \ - UMAP_SETTINGS=/srv/umap/umap/settings/docker.py \ PORT=8000 RUN mkdir -p /srv/umap/data && \ diff --git a/setup.cfg b/setup.cfg index caa1e364..0db56af5 100644 --- a/setup.cfg +++ b/setup.cfg @@ -29,6 +29,7 @@ install_requires = Django>=4.1 django-agnocomplete==2.2.0 django-compressor==4.3.1 + django-environ==0.10.0 Pillow==9.5.0 psycopg2==2.9.6 requests==2.30.0 diff --git a/umap/settings/__init__.py b/umap/settings/__init__.py index fc25bed1..aef9ce63 100644 --- a/umap/settings/__init__.py +++ b/umap/settings/__init__.py @@ -17,31 +17,30 @@ if not path: path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'local.py') if not os.path.exists(path): - msg = ('You must configure UMAP_SETTINGS or define ' - '/etc/umap/umap.conf') - print(colorize(msg, fg='red')) - sys.exit(1) + print(colorize('No valid UMAP_SETTINGS found', fg='yellow')) + path = None -d = types.ModuleType('config') -d.__file__ = path -try: - with open(path) as config_file: - exec(compile(config_file.read(), path, 'exec'), d.__dict__) -except IOError as e: - msg = 'Unable to import {} from UMAP_SETTINGS'.format(path) - print(colorize(msg, fg='red')) - sys.exit(e) -else: - print('Loaded local config from', path) - for key in dir(d): - if key.isupper(): - value = getattr(d, key) - if key.startswith('LEAFLET_STORAGE'): - # Retrocompat pre 1.0, remove me in 1.1. - globals()['UMAP' + key[15:]] = value - elif key == 'UMAP_CUSTOM_TEMPLATES': - globals()['TEMPLATES'][0]['DIRS'].insert(0, value) - elif key == 'UMAP_CUSTOM_STATICS': - globals()['STATICFILES_DIRS'].insert(0, value) - else: - globals()[key] = value +if path: + d = types.ModuleType('config') + d.__file__ = path + try: + with open(path) as config_file: + exec(compile(config_file.read(), path, 'exec'), d.__dict__) + except IOError as e: + msg = 'Unable to import {} from UMAP_SETTINGS'.format(path) + print(colorize(msg, fg='red')) + sys.exit(e) + else: + print('Loaded local config from', path) + for key in dir(d): + if key.isupper(): + value = getattr(d, key) + if key.startswith('LEAFLET_STORAGE'): + # Retrocompat pre 1.0, remove me in 1.1. + globals()['UMAP' + key[15:]] = value + elif key == 'UMAP_CUSTOM_TEMPLATES': + globals()['TEMPLATES'][0]['DIRS'].insert(0, value) + elif key == 'UMAP_CUSTOM_STATICS': + globals()['STATICFILES_DIRS'].insert(0, value) + else: + globals()[key] = value diff --git a/umap/settings/base.py b/umap/settings/base.py index 10b91139..07caa29a 100644 --- a/umap/settings/base.py +++ b/umap/settings/base.py @@ -1,13 +1,24 @@ """Base settings shared by all environments""" # Import global settings to make it easier to extend settings. +from email.utils import parseaddr + from django.template.defaultfilters import slugify from django.conf.locale import LANG_INFO +import environ + +env = environ.Env() # ============================================================================= # Generic Django project settings # ============================================================================= -DEBUG = True + +INTERNAL_IPS = env.list('INTERNAL_IPS', default='127.0.0.1') +ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['*']) +ADMINS = tuple(parseaddr(email) for email in env.list('ADMINS', default=[])) + + +DEBUG = env.bool('DEBUG', default=False) SITE_ID = 1 # Add languages we're missing from Django @@ -92,7 +103,7 @@ LANGUAGES = ( ) # Make this unique, and don't share it with anybody. -SECRET_KEY = '' +SECRET_KEY = env('SECRET_KEY', default=None) INSTALLED_APPS = ( 'django.contrib.auth', @@ -197,21 +208,25 @@ MIDDLEWARE = ( # Auth / security # ============================================================================= -ENABLE_ACCOUNT_LOGIN = False +# Set to True if login into django account should be possible. Default is to +# only use OAuth flow. +ENABLE_ACCOUNT_LOGIN = env.bool("ENABLE_ACCOUNT_LOGIN", default=False) # ============================================================================= # Miscellaneous project settings # ============================================================================= -UMAP_ALLOW_ANONYMOUS = False +UMAP_ALLOW_ANONYMOUS = env.bool("UMAP_ALLOW_ANONYMOUS", default=False) + UMAP_EXTRA_URLS = { 'routing': 'http://www.openstreetmap.org/directions?engine=osrm_car&route={lat},{lng}&locale={locale}#map={zoom}/{lat}/{lng}', # noqa 'ajax_proxy': '/ajax-proxy/?url={url}&ttl={ttl}', 'search': 'https://photon.komoot.io/api/?', } -UMAP_KEEP_VERSIONS = 10 -SITE_URL = "http://umap.org" +UMAP_KEEP_VERSIONS = env.int('UMAP_KEEP_VERSIONS', default=10) +SITE_URL = env("SITE_URL", default="http://umap.org") +SHORT_SITE_URL = env('SHORT_SITE_URL', default=None) SITE_NAME = 'uMap' -UMAP_DEMO_SITE = False +UMAP_DEMO_SITE = env('UMAP_DEMO_SITE', default=False) UMAP_EXCLUDE_DEFAULT_MAPS = False UMAP_MAPS_PER_PAGE = 5 UMAP_MAPS_PER_PAGE_OWNER = 10 @@ -219,15 +234,18 @@ UMAP_SEARCH_CONFIGURATION = "simple" UMAP_FEEDBACK_LINK = "https://wiki.openstreetmap.org/wiki/UMap#Feedback_and_help" # noqa USER_MAPS_URL = 'user_maps' DATABASES = { - 'default': { - 'ENGINE': 'django.contrib.gis.db.backends.postgis', - 'NAME': 'umap', - } + 'default': env.db(default='postgis://localhost:5432/umap') } -UMAP_READONLY = False + +UMAP_READONLY = env('UMAP_READONLY', default=False) UMAP_GZIP = True LOCALE_PATHS = [os.path.join(PROJECT_DIR, 'locale')] +LEAFLET_LONGITUDE = env.int('LEAFLET_LONGITUDE', default=2) +LEAFLET_LATITUDE = env.int('LEAFLET_LATITUDE', default=51) +LEAFLET_ZOOM = env.int('LEAFLET_ZOOM', default=6) + + # ============================================================================= # Third party app settings # ============================================================================= @@ -240,3 +258,21 @@ SOCIAL_AUTH_NO_DEFAULT_PROTECTED_USER_FIELDS = True SOCIAL_AUTH_PROTECTED_USER_FIELDS = ("id", ) LOGIN_URL = "login" SOCIAL_AUTH_LOGIN_REDIRECT_URL = "/login/popup/end/" + +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'console': { + 'level': 'ERROR', + 'filters': None, + 'class': 'logging.StreamHandler', + }, + }, + 'loggers': { + 'django': { + 'handlers': ['console'], + 'level': 'ERROR', + }, + }, +} diff --git a/umap/settings/docker.py b/umap/settings/docker.py deleted file mode 100644 index 097a35da..00000000 --- a/umap/settings/docker.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- coding:utf-8 -*- -""" -Settings for Docker development - -Use this file as a base for your local development settings and copy -it to umap/settings/local.py. It should not be checked into -your code repository. -""" -import environ -from umap.settings.base import * # pylint: disable=W0614,W0401 - -env = environ.Env() - -SECRET_KEY = env('SECRET_KEY') -INTERNAL_IPS = env.list('INTERNAL_IPS', default='127.0.0.1') -ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default='*') - -DEBUG = env.bool('DEBUG', default=False) - -ADMIN_EMAILS = env.list('ADMIN_EMAIL', default='') -ADMINS = [(email, email) for email in ADMIN_EMAILS] -MANAGERS = ADMINS - -DATABASES = { - 'default': env.db(default='postgis://localhost:5432/umap') -} - -COMPRESS_ENABLED = True -COMPRESS_OFFLINE = True - -LANGUAGE_CODE = 'en' - -# Set to False if login into django account should not be possible. You can -# administer accounts in the admin interface. -ENABLE_ACCOUNT_LOGIN = env.bool('ENABLE_ACCOUNT_LOGIN', default=True) - -AUTHENTICATION_BACKENDS = () - -# We need email to associate with other Oauth providers -SOCIAL_AUTH_GITHUB_SCOPE = ['user:email'] -SOCIAL_AUTH_GITHUB_KEY = env('GITHUB_KEY', default='') -SOCIAL_AUTH_GITHUB_SECRET = env('GITHUB_SECRET', default='') -if SOCIAL_AUTH_GITHUB_KEY and SOCIAL_AUTH_GITHUB_SECRET: - AUTHENTICATION_BACKENDS += ( - 'social_core.backends.github.GithubOAuth2', - ) -SOCIAL_AUTH_BITBUCKET_KEY = env('BITBUCKET_KEY', default='') -SOCIAL_AUTH_BITBUCKET_SECRET = env('BITBUCKET_SECRET', default='') -if SOCIAL_AUTH_BITBUCKET_KEY and SOCIAL_AUTH_BITBUCKET_SECRET: - AUTHENTICATION_BACKENDS += ( - 'social_core.backends.bitbucket.BitbucketOAuth', - ) - -SOCIAL_AUTH_TWITTER_KEY = env('TWITTER_KEY', default='') -SOCIAL_AUTH_TWITTER_SECRET = env('TWITTER_SECRET', default='') -if SOCIAL_AUTH_TWITTER_KEY and SOCIAL_AUTH_TWITTER_SECRET: - AUTHENTICATION_BACKENDS += ( - 'social_core.backends.twitter.TwitterOAuth', - ) -SOCIAL_AUTH_OPENSTREETMAP_KEY = env('OPENSTREETMAP_KEY', default='') -SOCIAL_AUTH_OPENSTREETMAP_SECRET = env('OPENSTREETMAP_SECRET', default='') -if SOCIAL_AUTH_OPENSTREETMAP_KEY and SOCIAL_AUTH_OPENSTREETMAP_SECRET: - AUTHENTICATION_BACKENDS += ( - 'social_core.backends.openstreetmap.OpenStreetMapOAuth', - ) - -AUTHENTICATION_BACKENDS += ( - 'django.contrib.auth.backends.ModelBackend', -) - -# MIDDLEWARE_CLASSES += ( -# 'social_django.middleware.SocialAuthExceptionMiddleware', -# ) - -SOCIAL_AUTH_RAISE_EXCEPTIONS = False -SOCIAL_AUTH_BACKEND_ERROR_URL = "/" - -# If you want to add a playgroud map, add its primary key -# UMAP_DEMO_PK = 204 -# If you want to add a showcase map on the home page, add its primary key -# UMAP_SHOWCASE_PK = 1156 -# Add a baner to warn people this instance is not production ready. -UMAP_DEMO_SITE = False - -# Whether to allow non authenticated people to create maps. -LEAFLET_STORAGE_ALLOW_ANONYMOUS = env.bool( - 'LEAFLET_STORAGE_ALLOW_ANONYMOUS', - default=False, -) - -# This setting will exclude empty maps (in fact, it will exclude all maps where -# the default center has not been updated) -UMAP_EXCLUDE_DEFAULT_MAPS = False - -# How many maps should be showcased on the main page resp. on the user page -UMAP_MAPS_PER_PAGE = 0 -# How many maps should be showcased on the user page, if owner -UMAP_MAPS_PER_PAGE_OWNER = 10 - -SITE_URL = env('SITE_URL') -SHORT_SITE_URL = env('SHORT_SITE_URL', default=None) - -CACHES = {'default': env.cache('REDIS_URL', default='locmem://')} - -# POSTGIS_VERSION = (2, 1, 0) -EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' - -# You need to unable accent extension before using UMAP_USE_UNACCENT -# python manage.py dbshell -# CREATE EXTENSION unaccent; -UMAP_USE_UNACCENT = False - -# For static deployment -STATIC_ROOT = '/srv/umap/static' - -# For users' statics (geojson mainly) -MEDIA_ROOT = '/srv/umap/uploads' - -# Default map location for new maps -LEAFLET_LONGITUDE = env.int('LEAFLET_LONGITUDE', default=2) -LEAFLET_LATITUDE = env.int('LEAFLET_LATITUDE', default=51) -LEAFLET_ZOOM = env.int('LEAFLET_ZOOM', default=6) - -# Number of old version to keep per datalayer. -LEAFLET_STORAGE_KEEP_VERSIONS = env.int( - 'LEAFLET_STORAGE_KEEP_VERSIONS', - default=10, -) - -import sys - -LOGGING = { - 'version': 1, - 'disable_existing_loggers': False, - 'formatters': { - 'verbose': { - 'format': '[django] %(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s' - } - }, - 'handlers': { - 'console': { - 'level': 'DEBUG', - 'class': 'logging.StreamHandler', - 'stream': sys.stdout, - 'formatter': 'verbose' - }, - }, - 'loggers': { - 'django': { - 'handlers': ['console'], - 'level': 'DEBUG', - 'propagate': True, - }, - }, -}