[API] handle missing URLs in episode action upload
[mygpo.git] / mygpo / settings.py
blob4227f03636e7dade868f30ce153f9b5b5348c818
1 # Django settings for mygpo project.
3 # This file is part of my.gpodder.org.
5 # my.gpodder.org is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Affero General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
10 # my.gpodder.org is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
13 # License for more details.
15 # You should have received a copy of the GNU Affero General Public License
16 # along with my.gpodder.org. If not, see <http://www.gnu.org/licenses/>.
19 import re
20 import sys
21 import os.path
22 import dj_database_url
25 BASE_DIR = os.path.dirname(os.path.abspath(__file__))
28 def get_bool(name, default):
29 return os.getenv(name, str(default)).lower() == 'true'
32 DEBUG = get_bool('DEBUG', False)
34 ADMINS = re.findall(r'\s*([^<]+) <([^>]+)>\s*', os.getenv('ADMINS', ''))
36 MANAGERS = ADMINS
38 DATABASES = {
39 'default': dj_database_url.config(
40 default='postgres://mygpo:mygpo@localhost/mygpo'),
44 _cache_used = bool(os.getenv('CACHE_BACKEND', False))
46 if _cache_used:
47 CACHES = {}
48 CACHES['default'] = {
49 'BACKEND': os.getenv(
50 'CACHE_BACKEND',
51 'django.core.cache.backends.memcached.MemcachedCache'),
52 'LOCATION': os.getenv('CACHE_LOCATION'),
56 # Local time zone for this installation. Choices can be found here:
57 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
58 # although not all choices may be available on all operating systems.
59 # If running in a Windows environment this must be set to the same as your
60 # system time zone.
61 TIME_ZONE = 'UTC'
63 # Language code for this installation. All choices can be found here:
64 # http://www.i18nguy.com/unicode/language-identifiers.html
65 LANGUAGE_CODE = 'en-us'
67 SITE_ID = 1
69 # If you set this to False, Django will make some optimizations so as not
70 # to load the internationalization machinery.
71 USE_I18N = True
73 STATIC_ROOT = 'staticfiles'
74 STATIC_URL = '/media/'
76 STATICFILES_DIRS = (
77 os.path.abspath(os.path.join(BASE_DIR, '..', 'htdocs', 'media')),
81 TEMPLATES = [{
82 'BACKEND': 'django.template.backends.django.DjangoTemplates',
83 'DIRS': [],
84 'OPTIONS': {
85 'context_processors': [
86 'django.contrib.auth.context_processors.auth',
87 'django.template.context_processors.debug',
88 'django.template.context_processors.i18n',
89 'django.template.context_processors.media',
90 'django.template.context_processors.static',
91 'django.template.context_processors.tz',
92 'django.contrib.messages.context_processors.messages',
93 'mygpo.web.google.analytics',
94 'mygpo.web.google.adsense',
95 # make the debug variable available in templates
96 # https://docs.djangoproject.com/en/dev/ref/templates/api/#django-core-context-processors-debug
97 'django.core.context_processors.debug',
99 # required so that the request obj can be accessed from
100 # templates. this is used to direct users to previous
101 # page after login
102 'django.core.context_processors.request',
104 'loaders': [
105 ('django.template.loaders.cached.Loader', [
106 'django.template.loaders.app_directories.Loader',
113 MIDDLEWARE_CLASSES = (
114 'django.middleware.common.CommonMiddleware',
115 'django.middleware.csrf.CsrfViewMiddleware',
116 'django.contrib.sessions.middleware.SessionMiddleware',
117 'django.contrib.auth.middleware.AuthenticationMiddleware',
118 'django.middleware.locale.LocaleMiddleware',
119 'django.contrib.messages.middleware.MessageMiddleware',
122 ROOT_URLCONF = 'mygpo.urls'
124 INSTALLED_APPS = (
125 'django.contrib.contenttypes',
126 'django.contrib.messages',
127 'django.contrib.admin',
128 'django.contrib.humanize',
129 'django.contrib.auth',
130 'django.contrib.sessions',
131 'django.contrib.staticfiles',
132 'django.contrib.sites',
133 'djcelery',
134 'mygpo.core',
135 'mygpo.podcasts',
136 'mygpo.chapters',
137 'mygpo.search',
138 'mygpo.users',
139 'mygpo.api',
140 'mygpo.web',
141 'mygpo.publisher',
142 'mygpo.subscriptions',
143 'mygpo.history',
144 'mygpo.favorites',
145 'mygpo.usersettings',
146 'mygpo.data',
147 'mygpo.userfeeds',
148 'mygpo.suggestions',
149 'mygpo.directory',
150 'mygpo.categories',
151 'mygpo.episodestates',
152 'mygpo.maintenance',
153 'mygpo.share',
154 'mygpo.administration',
155 'mygpo.pubsub',
156 'mygpo.podcastlists',
157 'mygpo.votes',
160 try:
161 import debug_toolbar
162 INSTALLED_APPS += ('debug_toolbar', )
164 except ImportError:
165 pass
168 try:
169 import opbeat
171 if not DEBUG:
172 INSTALLED_APPS += ('opbeat.contrib.django', )
174 # add opbeat middleware to the beginning of the middleware classes list
175 MIDDLEWARE_CLASSES = \
176 ('opbeat.contrib.django.middleware.OpbeatAPMMiddleware',) + \
177 MIDDLEWARE_CLASSES
179 except ImportError:
180 pass
183 ACCOUNT_ACTIVATION_DAYS = int(os.getenv('ACCOUNT_ACTIVATION_DAYS', 7))
185 AUTHENTICATION_BACKENDS = (
186 'mygpo.users.backend.CaseInsensitiveModelBackend',
187 'mygpo.web.auth.EmailAuthenticationBackend',
190 SESSION_ENGINE = "django.contrib.sessions.backends.cached_db"
192 # TODO: use (default) JSON serializer for security
193 # this would currently fail as we're (de)serializing datetime objects
194 # https://docs.djangoproject.com/en/1.5/topics/http/sessions/#session-serialization
195 SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
198 MESSAGE_STORAGE = 'django.contrib.messages.storage.session.SessionStorage'
200 USER_CLASS = 'mygpo.users.models.User'
202 LOGIN_URL = '/login/'
204 CSRF_FAILURE_VIEW = 'mygpo.web.views.security.csrf_failure'
207 DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL', '')
209 SECRET_KEY = os.getenv('SECRET_KEY', '')
211 if 'test' in sys.argv:
212 SECRET_KEY = 'test'
214 GOOGLE_ANALYTICS_PROPERTY_ID = os.getenv('GOOGLE_ANALYTICS_PROPERTY_ID', '')
216 DIRECTORY_EXCLUDED_TAGS = os.getenv('DIRECTORY_EXCLUDED_TAGS', '').split()
218 FLICKR_API_KEY = os.getenv('FLICKR_API_KEY', '')
220 SOUNDCLOUD_CONSUMER_KEY = os.getenv('SOUNDCLOUD_CONSUMER_KEY', '')
222 MAINTENANCE = get_bool('MAINTENANCE', False)
225 ALLOWED_HOSTS = ['*']
228 LOGGING = {
229 'version': 1,
230 'disable_existing_loggers': False,
231 'formatters': {
232 'verbose': {
233 'format': '%(asctime)s %(name)s %(levelname)s %(message)s',
236 'filters': {
237 'require_debug_false': {
238 '()': 'django.utils.log.RequireDebugFalse'
241 'handlers': {
242 'console': {
243 'level': os.getenv('LOGGING_CONSOLE_LEVEL', 'DEBUG'),
244 'class': 'logging.StreamHandler',
245 'formatter': 'verbose',
247 'mail_admins': {
248 'level': 'ERROR',
249 'filters': ['require_debug_false'],
250 'class': 'django.utils.log.AdminEmailHandler',
253 'loggers': {
254 'django': {
255 'handlers': os.getenv('LOGGING_DJANGO_HANDLERS',
256 'console').split(),
257 'propagate': True,
258 'level': os.getenv('LOGGING_DJANGO_LEVEL', 'WARN'),
260 'mygpo': {
261 'handlers': os.getenv('LOGGING_MYGPO_HANDLERS', 'console').split(),
262 'level': os.getenv('LOGGING_MYGPO_LEVEL', 'INFO'),
264 'celery': {
265 'handlers': os.getenv('LOGGING_CELERY_HANDLERS',
266 'console').split(),
267 'level': os.getenv('LOGGING_CELERY_LEVEL', 'DEBUG'),
272 _use_log_file = bool(os.getenv('LOGGING_FILENAME', False))
274 if _use_log_file:
275 LOGGING['handlers']['file'] = {
276 'level': 'INFO',
277 'class': 'logging.handlers.RotatingFileHandler',
278 'filename': os.getenv('LOGGING_FILENAME'),
279 'maxBytes': 10000000,
280 'backupCount': 10,
281 'formatter': 'verbose',
285 # minimum number of subscribers a podcast must have to be assigned a slug
286 PODCAST_SLUG_SUBSCRIBER_LIMIT = int(os.getenv(
287 'PODCAST_SLUG_SUBSCRIBER_LIMIT', 10))
289 # minimum number of subscribers that a podcast needs to "push" one of its
290 # categories to the top
291 MIN_SUBSCRIBERS_CATEGORY = int(os.getenv('MIN_SUBSCRIBERS_CATEGORY', 10))
293 # maximum number of episode actions that the API processes immediatelly before
294 # returning the response. Larger requests will be handled in background.
295 # Handler can be set to None to disable
296 API_ACTIONS_MAX_NONBG = int(os.getenv('API_ACTIONS_MAX_NONBG', 100))
297 API_ACTIONS_BG_HANDLER = 'mygpo.api.tasks.episode_actions_celery_handler'
300 ADSENSE_CLIENT = os.getenv('ADSENSE_CLIENT', '')
302 ADSENSE_SLOT_BOTTOM = os.getenv('ADSENSE_SLOT_BOTTOM', '')
304 # we're running behind a proxy that sets the X-Forwarded-Proto header correctly
305 # see https://docs.djangoproject.com/en/dev/ref/settings/#secure-proxy-ssl-header
306 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
309 # enabled access to staff-only areas with ?staff=<STAFF_TOKEN>
310 STAFF_TOKEN = os.getenv('STAFF_TOKEN', None)
312 # Flattr settings -- available after you register your app
313 FLATTR_KEY = os.getenv('FLATTR_KEY', '')
314 FLATTR_SECRET = os.getenv('FLATTR_SECRET', '')
316 # Flattr thing of the webservice. Will be flattr'd when a user sets
317 # the "Auto-Flattr gpodder.net" option
318 FLATTR_MYGPO_THING = os.getenv(
319 'FLATTR_MYGPO_THING',
320 'https://flattr.com/submit/auto?user_id=stefankoegl&url=http://gpodder.net'
323 # The User-Agent string used for outgoing HTTP requests
324 USER_AGENT = 'gpodder.net (+https://github.com/gpodder/mygpo)'
326 # Base URL of the website that is used if the actually used parameters is not
327 # available. Request handlers, for example, can access the requested domain.
328 # Code that runs in background can not do this, and therefore requires a
329 # default value. This should be set to something like 'http://example.com'
330 DEFAULT_BASE_URL = os.getenv('DEFAULT_BASE_URL', '')
333 ### Celery
335 BROKER_URL = os.getenv('BROKER_URL', 'redis://localhost')
336 CELERY_RESULT_BACKEND = 'djcelery.backends.database:DatabaseBackend'
338 SERVER_EMAIL = os.getenv('SERVER_EMAIL', 'no-reply@example.com')
340 CELERY_TASK_RESULT_EXPIRES = 60 * 60 # 1h expiry time in seconds
342 CELERY_ACCEPT_CONTENT = ['pickle', 'json']
344 CELERY_SEND_TASK_ERROR_EMAILS = get_bool('CELERY_SEND_TASK_ERROR_EMAILS',
345 False)
347 ### Google API
349 GOOGLE_CLIENT_ID = os.getenv('GOOGLE_CLIENT_ID', '')
350 GOOGLE_CLIENT_SECRET = os.getenv('GOOGLE_CLIENT_SECRET', '')
352 # URL where users of the site can get support
353 SUPPORT_URL = os.getenv('SUPPORT_URL', '')
356 FEEDSERVICE_URL = os.getenv('FEEDSERVICE_URL', 'http://feeds.gpodder.net/')
358 # Elasticsearch settings
360 ELASTICSEARCH_SERVER = os.getenv('ELASTICSEARCH_SERVER', '127.0.0.1:9200')
361 ELASTICSEARCH_INDEX = os.getenv('ELASTICSEARCH_INDEX', 'mygpo')
362 ELASTICSEARCH_TIMEOUT = float(os.getenv('ELASTICSEARCH_TIMEOUT', '2'))
364 # time for how long an activation is valid; after that, an unactivated user
365 # will be deleted
366 ACTIVATION_VALID_DAYS = int(os.getenv('ACTIVATION_VALID_DAYS', 10))
369 OPBEAT = {
370 "ORGANIZATION_ID": os.getenv('OPBEAT_ORGANIZATION_ID', ''),
371 "APP_ID": os.getenv('OPBEAT_APP_ID', ''),
372 "SECRET_TOKEN": os.getenv('OPBEAT_SECRET_TOKEN', ''),
376 INTERNAL_IPS = os.getenv('INTERNAL_IPS', '').split()
378 EMAIL_BACKEND = os.getenv('EMAIL_BACKEND',
379 'django.core.mail.backends.smtp.EmailBackend')