common.py 16.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
# -*- coding: utf-8 -*-
"""
Django settings for funkwhale_api project.

For more information on this file, see
https://docs.djangoproject.com/en/dev/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/dev/ref/settings/
"""
from __future__ import absolute_import, unicode_literals

13
import datetime
14
import os
15
16
from urllib.parse import urlparse, urlsplit

17
import environ
18
19
from celery.schedules import crontab

Eliot Berriot's avatar
Eliot Berriot committed
20
from funkwhale_api import __version__
21
22

ROOT_DIR = environ.Path(__file__) - 3  # (/a/b/myfile.py - 3 = /)
Eliot Berriot's avatar
Eliot Berriot committed
23
APPS_DIR = ROOT_DIR.path("funkwhale_api")
24
25
26
27

env = environ.Env()

try:
Eliot Berriot's avatar
Eliot Berriot committed
28
    env.read_env(ROOT_DIR.file(".env"))
29
30
except FileNotFoundError:
    pass
31

32
FUNKWHALE_HOSTNAME = None
Eliot Berriot's avatar
Eliot Berriot committed
33
34
FUNKWHALE_HOSTNAME_SUFFIX = env("FUNKWHALE_HOSTNAME_SUFFIX", default=None)
FUNKWHALE_HOSTNAME_PREFIX = env("FUNKWHALE_HOSTNAME_PREFIX", default=None)
35
36
if FUNKWHALE_HOSTNAME_PREFIX and FUNKWHALE_HOSTNAME_SUFFIX:
    # We're in traefik case, in development
Eliot Berriot's avatar
Eliot Berriot committed
37
38
39
40
    FUNKWHALE_HOSTNAME = "{}.{}".format(
        FUNKWHALE_HOSTNAME_PREFIX, FUNKWHALE_HOSTNAME_SUFFIX
    )
    FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
41
42
else:
    try:
Eliot Berriot's avatar
Eliot Berriot committed
43
44
        FUNKWHALE_HOSTNAME = env("FUNKWHALE_HOSTNAME")
        FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
45
    except Exception:
Eliot Berriot's avatar
Eliot Berriot committed
46
        FUNKWHALE_URL = env("FUNKWHALE_URL")
47
48
49
50
        _parsed = urlsplit(FUNKWHALE_URL)
        FUNKWHALE_HOSTNAME = _parsed.netloc
        FUNKWHALE_PROTOCOL = _parsed.scheme

Eliot Berriot's avatar
Eliot Berriot committed
51
FUNKWHALE_URL = "{}://{}".format(FUNKWHALE_PROTOCOL, FUNKWHALE_HOSTNAME)
52

53

54
# XXX: deprecated, see #186
Eliot Berriot's avatar
Eliot Berriot committed
55
56
FEDERATION_ENABLED = env.bool("FEDERATION_ENABLED", default=True)
FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME)
57
# XXX: deprecated, see #186
Eliot Berriot's avatar
Eliot Berriot committed
58
FEDERATION_COLLECTION_PAGE_SIZE = env.int("FEDERATION_COLLECTION_PAGE_SIZE", default=50)
59
# XXX: deprecated, see #186
60
FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
Eliot Berriot's avatar
Eliot Berriot committed
61
    "FEDERATION_MUSIC_NEEDS_APPROVAL", default=True
62
)
63
# XXX: deprecated, see #186
Eliot Berriot's avatar
Eliot Berriot committed
64
65
FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12)
ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS")
66

67
68
69
# APP CONFIGURATION
# ------------------------------------------------------------------------------
DJANGO_APPS = (
Eliot Berriot's avatar
Eliot Berriot committed
70
    "channels",
71
    # Default Django apps:
Eliot Berriot's avatar
Eliot Berriot committed
72
73
74
75
76
77
78
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.sites",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "django.contrib.postgres",
79
80
81
    # Useful template tags:
    # 'django.contrib.humanize',
    # Admin
Eliot Berriot's avatar
Eliot Berriot committed
82
    "django.contrib.admin",
83
84
85
)
THIRD_PARTY_APPS = (
    # 'crispy_forms',  # Form layouts
Eliot Berriot's avatar
Eliot Berriot committed
86
87
88
89
90
91
92
93
94
95
96
97
98
    "allauth",  # registration
    "allauth.account",  # registration
    "allauth.socialaccount",  # registration
    "corsheaders",
    "rest_framework",
    "rest_framework.authtoken",
    "taggit",
    "rest_auth",
    "rest_auth.registration",
    "dynamic_preferences",
    "django_filters",
    "cacheops",
    "django_cleanup",
99
100
)

Eliot Berriot's avatar
Eliot Berriot committed
101
102
103

# Sentry
RAVEN_ENABLED = env.bool("RAVEN_ENABLED", default=False)
Eliot Berriot's avatar
Eliot Berriot committed
104
RAVEN_DSN = env("RAVEN_DSN", default="")
Eliot Berriot's avatar
Eliot Berriot committed
105
106
107

if RAVEN_ENABLED:
    RAVEN_CONFIG = {
Eliot Berriot's avatar
Eliot Berriot committed
108
        "dsn": RAVEN_DSN,
Eliot Berriot's avatar
Eliot Berriot committed
109
110
        # If you are using git, you can also automatically configure the
        # release based on the git info.
Eliot Berriot's avatar
Eliot Berriot committed
111
        "release": __version__,
Eliot Berriot's avatar
Eliot Berriot committed
112
    }
Eliot Berriot's avatar
Eliot Berriot committed
113
    THIRD_PARTY_APPS += ("raven.contrib.django.raven_compat",)
Eliot Berriot's avatar
Eliot Berriot committed
114
115


116
117
# Apps specific for this project go here.
LOCAL_APPS = (
Eliot Berriot's avatar
Eliot Berriot committed
118
119
120
    "funkwhale_api.common",
    "funkwhale_api.activity.apps.ActivityConfig",
    "funkwhale_api.users",  # custom users app
121
    # Your stuff: custom apps go here
Eliot Berriot's avatar
Eliot Berriot committed
122
123
124
125
126
127
128
129
130
131
132
133
    "funkwhale_api.instance",
    "funkwhale_api.music",
    "funkwhale_api.requests",
    "funkwhale_api.favorites",
    "funkwhale_api.federation",
    "funkwhale_api.radios",
    "funkwhale_api.history",
    "funkwhale_api.playlists",
    "funkwhale_api.providers.audiofile",
    "funkwhale_api.providers.youtube",
    "funkwhale_api.providers.acoustid",
    "funkwhale_api.subsonic",
134
135
136
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
Eliot Berriot's avatar
Eliot Berriot committed
137

138
139
140
141
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS

# MIDDLEWARE CONFIGURATION
# ------------------------------------------------------------------------------
Eliot Berriot's avatar
Eliot Berriot committed
142
MIDDLEWARE = (
143
    # Make sure djangosecure.middleware.SecurityMiddleware is listed first
Eliot Berriot's avatar
Eliot Berriot committed
144
145
146
147
148
149
150
    "django.contrib.sessions.middleware.SessionMiddleware",
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
151
152
153
154
)

# MIGRATIONS CONFIGURATION
# ------------------------------------------------------------------------------
Eliot Berriot's avatar
Eliot Berriot committed
155
MIGRATION_MODULES = {"sites": "funkwhale_api.contrib.sites.migrations"}
156
157
158
159
160
161
162
163
164

# DEBUG
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = env.bool("DJANGO_DEBUG", False)

# FIXTURE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-FIXTURE_DIRS
Eliot Berriot's avatar
Eliot Berriot committed
165
FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
166
167
168

# EMAIL CONFIGURATION
# ------------------------------------------------------------------------------
169
170
171
172

# EMAIL
# ------------------------------------------------------------------------------
DEFAULT_FROM_EMAIL = env(
Eliot Berriot's avatar
Eliot Berriot committed
173
174
    "DEFAULT_FROM_EMAIL", default="Funkwhale <noreply@{}>".format(FUNKWHALE_HOSTNAME)
)
175

Eliot Berriot's avatar
Eliot Berriot committed
176
177
EMAIL_SUBJECT_PREFIX = env("EMAIL_SUBJECT_PREFIX", default="[Funkwhale] ")
SERVER_EMAIL = env("SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
178
179


Eliot Berriot's avatar
Eliot Berriot committed
180
EMAIL_CONFIG = env.email_url("EMAIL_CONFIG", default="consolemail://")
181
182

vars().update(EMAIL_CONFIG)
183
184
185
186
187
188

# DATABASE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
    # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
Eliot Berriot's avatar
Eliot Berriot committed
189
    "default": env.db("DATABASE_URL")
190
}
Eliot Berriot's avatar
Eliot Berriot committed
191
DATABASES["default"]["ATOMIC_REQUESTS"] = True
192
193
194
195
196
197
198
199
200
201
202
203
204
#
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': 'db.sqlite3',
#     }
# }
# GENERAL CONFIGURATION
# ------------------------------------------------------------------------------
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
# In a Windows environment this must be set to your system time zone.
Eliot Berriot's avatar
Eliot Berriot committed
205
TIME_ZONE = "UTC"
206
207

# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
Eliot Berriot's avatar
Eliot Berriot committed
208
LANGUAGE_CODE = "en-us"
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227

# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True

# TEMPLATE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#templates
TEMPLATES = [
    {
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#std:setting-TEMPLATES-BACKEND
Eliot Berriot's avatar
Eliot Berriot committed
228
        "BACKEND": "django.template.backends.django.DjangoTemplates",
229
        # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
Eliot Berriot's avatar
Eliot Berriot committed
230
231
        "DIRS": [str(APPS_DIR.path("templates"))],
        "OPTIONS": {
232
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
Eliot Berriot's avatar
Eliot Berriot committed
233
            "debug": DEBUG,
234
235
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
            # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
Eliot Berriot's avatar
Eliot Berriot committed
236
237
238
            "loaders": [
                "django.template.loaders.filesystem.Loader",
                "django.template.loaders.app_directories.Loader",
239
240
            ],
            # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
Eliot Berriot's avatar
Eliot Berriot committed
241
242
243
244
245
246
247
248
249
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.template.context_processors.i18n",
                "django.template.context_processors.media",
                "django.template.context_processors.static",
                "django.template.context_processors.tz",
                "django.contrib.messages.context_processors.messages",
250
251
252
                # Your stuff: custom template context processors go here
            ],
        },
Eliot Berriot's avatar
Eliot Berriot committed
253
    }
254
255
256
]

# See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs
Eliot Berriot's avatar
Eliot Berriot committed
257
CRISPY_TEMPLATE_PACK = "bootstrap3"
258
259
260
261

# STATIC FILE CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
Eliot Berriot's avatar
Eliot Berriot committed
262
STATIC_ROOT = env("STATIC_ROOT", default=str(ROOT_DIR("staticfiles")))
263
264

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
Eliot Berriot's avatar
Eliot Berriot committed
265
266
STATIC_URL = env("STATIC_URL", default="/staticfiles/")
DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIFileSystemStorage"
267
268

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
Eliot Berriot's avatar
Eliot Berriot committed
269
STATICFILES_DIRS = (str(APPS_DIR.path("static")),)
270
271
272

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
STATICFILES_FINDERS = (
Eliot Berriot's avatar
Eliot Berriot committed
273
274
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder",
275
276
277
278
279
)

# MEDIA CONFIGURATION
# ------------------------------------------------------------------------------
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
Eliot Berriot's avatar
Eliot Berriot committed
280
MEDIA_ROOT = env("MEDIA_ROOT", default=str(APPS_DIR("media")))
281
282

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
Eliot Berriot's avatar
Eliot Berriot committed
283
MEDIA_URL = env("MEDIA_URL", default="/media/")
284
285
286

# URL Configuration
# ------------------------------------------------------------------------------
Eliot Berriot's avatar
Eliot Berriot committed
287
ROOT_URLCONF = "config.urls"
288
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
Eliot Berriot's avatar
Eliot Berriot committed
289
WSGI_APPLICATION = "config.wsgi.application"
Eliot Berriot's avatar
Eliot Berriot committed
290
ASGI_APPLICATION = "config.routing.application"
291

292
# This ensures that Django will be able to detect a secure connection
Eliot Berriot's avatar
Eliot Berriot committed
293
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
294

295
296
297
# AUTHENTICATION CONFIGURATION
# ------------------------------------------------------------------------------
AUTHENTICATION_BACKENDS = (
Eliot Berriot's avatar
Eliot Berriot committed
298
299
    "django.contrib.auth.backends.ModelBackend",
    "allauth.account.auth_backends.AuthenticationBackend",
300
)
301
SESSION_COOKIE_HTTPONLY = False
302
# Some really nice defaults
Eliot Berriot's avatar
Eliot Berriot committed
303
ACCOUNT_AUTHENTICATION_METHOD = "username_email"
304
ACCOUNT_EMAIL_REQUIRED = True
Eliot Berriot's avatar
Eliot Berriot committed
305
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
306
307
308

# Custom user app defaults
# Select the correct user model
Eliot Berriot's avatar
Eliot Berriot committed
309
310
311
AUTH_USER_MODEL = "users.User"
LOGIN_REDIRECT_URL = "users:redirect"
LOGIN_URL = "account_login"
312
313

# SLUGLIFIER
Eliot Berriot's avatar
Eliot Berriot committed
314
AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify"
315

316
CACHE_DEFAULT = "redis://127.0.0.1:6379/0"
Eliot Berriot's avatar
Eliot Berriot committed
317
CACHES = {"default": env.cache_url("CACHE_URL", default=CACHE_DEFAULT)}
318

319
CACHES["default"]["BACKEND"] = "django_redis.cache.RedisCache"
Eliot Berriot's avatar
Eliot Berriot committed
320
321

cache_url = urlparse(CACHES["default"]["LOCATION"])
Eliot Berriot's avatar
Eliot Berriot committed
322
323
324
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
Eliot Berriot's avatar
Eliot Berriot committed
325
326
        "CONFIG": {"hosts": [(cache_url.hostname, cache_url.port)]},
    }
Eliot Berriot's avatar
Eliot Berriot committed
327
328
}

329
330
331
CACHES["default"]["OPTIONS"] = {
    "CLIENT_CLASS": "django_redis.client.DefaultClient",
    "IGNORE_EXCEPTIONS": True,  # mimics memcache behavior.
Eliot Berriot's avatar
Eliot Berriot committed
332
    # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
333
334
335
336
}


########## CELERY
Eliot Berriot's avatar
Eliot Berriot committed
337
INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",)
338
CELERY_BROKER_URL = env(
Eliot Berriot's avatar
Eliot Berriot committed
339
340
    "CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT)
)
341
########## END CELERY
342
# Location of root django.contrib.admin URL, use {% url 'admin:index' %}
Eliot Berriot's avatar
Eliot Berriot committed
343

344
# Your common stuff: Below this line define 3rd party library settings
345
346
CELERY_TASK_DEFAULT_RATE_LIMIT = 1
CELERY_TASK_TIME_LIMIT = 300
347
CELERYBEAT_SCHEDULE = {
Eliot Berriot's avatar
Eliot Berriot committed
348
349
350
351
    "federation.clean_music_cache": {
        "task": "funkwhale_api.federation.tasks.clean_music_cache",
        "schedule": crontab(hour="*/2"),
        "options": {"expires": 60 * 2},
352
353
354
    }
}

355
JWT_AUTH = {
Eliot Berriot's avatar
Eliot Berriot committed
356
357
358
359
360
    "JWT_ALLOW_REFRESH": True,
    "JWT_EXPIRATION_DELTA": datetime.timedelta(days=7),
    "JWT_REFRESH_EXPIRATION_DELTA": datetime.timedelta(days=30),
    "JWT_AUTH_HEADER_PREFIX": "JWT",
    "JWT_GET_USER_SECRET_KEY": lambda user: user.secret_key,
361
}
362
OLD_PASSWORD_FIELD_ENABLED = True
Eliot Berriot's avatar
Eliot Berriot committed
363
ACCOUNT_ADAPTER = "funkwhale_api.users.adapters.FunkwhaleAccountAdapter"
364
365
366
367
368
369
CORS_ORIGIN_ALLOW_ALL = True
# CORS_ORIGIN_WHITELIST = (
#     'localhost',
#     'funkwhale.localhost',
# )
CORS_ALLOW_CREDENTIALS = True
370

371
REST_FRAMEWORK = {
Eliot Berriot's avatar
Eliot Berriot committed
372
373
374
375
376
377
378
379
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_PAGINATION_CLASS": "funkwhale_api.common.pagination.FunkwhalePagination",
    "PAGE_SIZE": 25,
    "DEFAULT_PARSER_CLASSES": (
        "rest_framework.parsers.JSONParser",
        "rest_framework.parsers.FormParser",
        "rest_framework.parsers.MultiPartParser",
        "funkwhale_api.federation.parsers.ActivityParser",
380
    ),
Eliot Berriot's avatar
Eliot Berriot committed
381
382
383
384
385
386
    "DEFAULT_AUTHENTICATION_CLASSES": (
        "funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS",
        "funkwhale_api.common.authentication.BearerTokenHeaderAuth",
        "rest_framework_jwt.authentication.JSONWebTokenAuthentication",
        "rest_framework.authentication.SessionAuthentication",
        "rest_framework.authentication.BasicAuthentication",
387
    ),
Eliot Berriot's avatar
Eliot Berriot committed
388
389
390
    "DEFAULT_FILTER_BACKENDS": (
        "rest_framework.filters.OrderingFilter",
        "django_filters.rest_framework.DjangoFilterBackend",
391
    ),
Eliot Berriot's avatar
Eliot Berriot committed
392
    "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",),
393
}
394

Eliot Berriot's avatar
Eliot Berriot committed
395
BROWSABLE_API_ENABLED = env.bool("BROWSABLE_API_ENABLED", default=False)
396
if BROWSABLE_API_ENABLED:
Eliot Berriot's avatar
Eliot Berriot committed
397
398
    REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"] += (
        "rest_framework.renderers.BrowsableAPIRenderer",
399
400
    )

401
REST_AUTH_SERIALIZERS = {
Eliot Berriot's avatar
Eliot Berriot committed
402
    "PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer"  # noqa
403
404
405
}
REST_SESSION_LOGIN = False
REST_USE_JWT = True
406
407

ATOMIC_REQUESTS = False
408
409
USE_X_FORWARDED_HOST = True
USE_X_FORWARDED_PORT = True
410
411
412

# Wether we should use Apache, Nginx (or other) headers when serving audio files
# Default to Nginx
Eliot Berriot's avatar
Eliot Berriot committed
413
414
REVERSE_PROXY_TYPE = env("REVERSE_PROXY_TYPE", default="nginx")
assert REVERSE_PROXY_TYPE in ["apache2", "nginx"], "Unsupported REVERSE_PROXY_TYPE"
415

416
417
# Which path will be used to process the internal redirection
# **DO NOT** put a slash at the end
Eliot Berriot's avatar
Eliot Berriot committed
418
PROTECT_FILES_PATH = env("PROTECT_FILES_PATH", default="/_protected")
419
420
421
422


# use this setting to tweak for how long you want to cache
# musicbrainz results. (value is in seconds)
Eliot Berriot's avatar
Eliot Berriot committed
423
424
425
MUSICBRAINZ_CACHE_DURATION = env.int("MUSICBRAINZ_CACHE_DURATION", default=300)
CACHEOPS_REDIS = env("CACHE_URL", default=CACHE_DEFAULT)
CACHEOPS_ENABLED = env.bool("CACHEOPS_ENABLED", default=True)
426
CACHEOPS = {
Eliot Berriot's avatar
Eliot Berriot committed
427
428
429
430
431
    "music.artist": {"ops": "all", "timeout": 60 * 60},
    "music.album": {"ops": "all", "timeout": 60 * 60},
    "music.track": {"ops": "all", "timeout": 60 * 60},
    "music.trackfile": {"ops": "all", "timeout": 60 * 60},
    "taggit.tag": {"ops": "all", "timeout": 60 * 60},
432
}
433

434
# Custom Admin URL, use {% url 'admin:index' %}
Eliot Berriot's avatar
Eliot Berriot committed
435
ADMIN_URL = env("DJANGO_ADMIN_URL", default="^api/admin/")
436
CSRF_USE_SESSIONS = True
437
438

# Playlist settings
439
# XXX: deprecated, see #186
Eliot Berriot's avatar
Eliot Berriot committed
440
PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
441
442

ACCOUNT_USERNAME_BLACKLIST = [
Eliot Berriot's avatar
Eliot Berriot committed
443
444
445
446
447
448
449
450
451
452
453
454
455
    "funkwhale",
    "library",
    "test",
    "status",
    "root",
    "admin",
    "owner",
    "superuser",
    "staff",
    "service",
] + env.list("ACCOUNT_USERNAME_BLACKLIST", default=[])

EXTERNAL_REQUESTS_VERIFY_SSL = env.bool("EXTERNAL_REQUESTS_VERIFY_SSL", default=True)
456
457
# XXX: deprecated, see #186
API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
458

Eliot Berriot's avatar
Eliot Berriot committed
459
MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
460
461
462
# on Docker setup, the music directory may not match the host path,
# and we need to know it for it to serve stuff properly
MUSIC_DIRECTORY_SERVE_PATH = env(
Eliot Berriot's avatar
Eliot Berriot committed
463
464
    "MUSIC_DIRECTORY_SERVE_PATH", default=MUSIC_DIRECTORY_PATH
)