kopia lustrzana https://dev.funkwhale.audio/funkwhale/funkwhale
				
				
				
			
		
			
				
	
	
		
			598 wiersze
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			598 wiersze
		
	
	
		
			21 KiB
		
	
	
	
		
			Python
		
	
	
| # -*- 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
 | |
| 
 | |
| import datetime
 | |
| import logging
 | |
| 
 | |
| from urllib.parse import urlsplit
 | |
| 
 | |
| import environ
 | |
| from celery.schedules import crontab
 | |
| 
 | |
| from funkwhale_api import __version__
 | |
| 
 | |
| logger = logging.getLogger(__name__)
 | |
| ROOT_DIR = environ.Path(__file__) - 3  # (/a/b/myfile.py - 3 = /)
 | |
| APPS_DIR = ROOT_DIR.path("funkwhale_api")
 | |
| 
 | |
| env = environ.Env()
 | |
| env_file = env("ENV_FILE", default=None)
 | |
| if env_file:
 | |
|     # we have an explicitely specified env file
 | |
|     # so we try to load and it fail loudly if it does not exist
 | |
|     print("ENV_FILE", env_file)
 | |
|     env.read_env(env_file)
 | |
| else:
 | |
|     # we try to load from .env and config/.env
 | |
|     # but do not crash if those files don't exist
 | |
|     paths = [
 | |
|         # /srv/funwhale/api/.env
 | |
|         ROOT_DIR,
 | |
|         # /srv/funwhale/config/.env
 | |
|         ((ROOT_DIR - 1) + "config"),
 | |
|     ]
 | |
|     for path in paths:
 | |
|         try:
 | |
|             env_path = path.file(".env")
 | |
|         except FileNotFoundError:
 | |
|             logger.debug("No env file found at %s/.env", path)
 | |
|             continue
 | |
|         env.read_env(env_path)
 | |
|         logger.info("Loaded env file at %s/.env", path)
 | |
|         break
 | |
| 
 | |
| FUNKWHALE_HOSTNAME = None
 | |
| FUNKWHALE_HOSTNAME_SUFFIX = env("FUNKWHALE_HOSTNAME_SUFFIX", default=None)
 | |
| FUNKWHALE_HOSTNAME_PREFIX = env("FUNKWHALE_HOSTNAME_PREFIX", default=None)
 | |
| if FUNKWHALE_HOSTNAME_PREFIX and FUNKWHALE_HOSTNAME_SUFFIX:
 | |
|     # We're in traefik case, in development
 | |
|     FUNKWHALE_HOSTNAME = "{}.{}".format(
 | |
|         FUNKWHALE_HOSTNAME_PREFIX, FUNKWHALE_HOSTNAME_SUFFIX
 | |
|     )
 | |
|     FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
 | |
| else:
 | |
|     try:
 | |
|         FUNKWHALE_HOSTNAME = env("FUNKWHALE_HOSTNAME")
 | |
|         FUNKWHALE_PROTOCOL = env("FUNKWHALE_PROTOCOL", default="https")
 | |
|     except Exception:
 | |
|         FUNKWHALE_URL = env("FUNKWHALE_URL")
 | |
|         _parsed = urlsplit(FUNKWHALE_URL)
 | |
|         FUNKWHALE_HOSTNAME = _parsed.netloc
 | |
|         FUNKWHALE_PROTOCOL = _parsed.scheme
 | |
| 
 | |
| FUNKWHALE_PROTOCOL = FUNKWHALE_PROTOCOL.lower()
 | |
| FUNKWHALE_HOSTNAME = FUNKWHALE_HOSTNAME.lower()
 | |
| FUNKWHALE_URL = "{}://{}".format(FUNKWHALE_PROTOCOL, FUNKWHALE_HOSTNAME)
 | |
| FUNKWHALE_SPA_HTML_ROOT = env(
 | |
|     "FUNKWHALE_SPA_HTML_ROOT", default=FUNKWHALE_URL + "/front/"
 | |
| )
 | |
| FUNKWHALE_SPA_HTML_CACHE_DURATION = env.int(
 | |
|     "FUNKWHALE_SPA_HTML_CACHE_DURATION", default=60 * 15
 | |
| )
 | |
| FUNKWHALE_EMBED_URL = env(
 | |
|     "FUNKWHALE_EMBED_URL", default=FUNKWHALE_SPA_HTML_ROOT + "embed.html"
 | |
| )
 | |
| APP_NAME = "Funkwhale"
 | |
| 
 | |
| # XXX: deprecated, see #186
 | |
| FEDERATION_ENABLED = env.bool("FEDERATION_ENABLED", default=True)
 | |
| FEDERATION_HOSTNAME = env("FEDERATION_HOSTNAME", default=FUNKWHALE_HOSTNAME).lower()
 | |
| # XXX: deprecated, see #186
 | |
| FEDERATION_COLLECTION_PAGE_SIZE = env.int("FEDERATION_COLLECTION_PAGE_SIZE", default=50)
 | |
| # XXX: deprecated, see #186
 | |
| FEDERATION_MUSIC_NEEDS_APPROVAL = env.bool(
 | |
|     "FEDERATION_MUSIC_NEEDS_APPROVAL", default=True
 | |
| )
 | |
| # XXX: deprecated, see #186
 | |
| FEDERATION_ACTOR_FETCH_DELAY = env.int("FEDERATION_ACTOR_FETCH_DELAY", default=60 * 12)
 | |
| ALLOWED_HOSTS = env.list("DJANGO_ALLOWED_HOSTS", default=[]) + [FUNKWHALE_HOSTNAME]
 | |
| 
 | |
| # APP CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| DJANGO_APPS = (
 | |
|     "channels",
 | |
|     # Default Django apps:
 | |
|     "django.contrib.auth",
 | |
|     "django.contrib.contenttypes",
 | |
|     "django.contrib.sessions",
 | |
|     "django.contrib.sites",
 | |
|     "django.contrib.messages",
 | |
|     "django.contrib.staticfiles",
 | |
|     "django.contrib.postgres",
 | |
|     # Useful template tags:
 | |
|     # 'django.contrib.humanize',
 | |
|     # Admin
 | |
|     "django.contrib.admin",
 | |
| )
 | |
| THIRD_PARTY_APPS = (
 | |
|     # 'crispy_forms',  # Form layouts
 | |
|     "allauth",  # registration
 | |
|     "allauth.account",  # registration
 | |
|     "allauth.socialaccount",  # registration
 | |
|     "corsheaders",
 | |
|     "rest_framework",
 | |
|     "rest_framework.authtoken",
 | |
|     "taggit",
 | |
|     "rest_auth",
 | |
|     "rest_auth.registration",
 | |
|     "dynamic_preferences",
 | |
|     "django_filters",
 | |
|     "django_cleanup",
 | |
|     "versatileimagefield",
 | |
| )
 | |
| 
 | |
| 
 | |
| # Sentry
 | |
| RAVEN_ENABLED = env.bool("RAVEN_ENABLED", default=False)
 | |
| RAVEN_DSN = env("RAVEN_DSN", default="")
 | |
| 
 | |
| if RAVEN_ENABLED:
 | |
|     RAVEN_CONFIG = {
 | |
|         "dsn": RAVEN_DSN,
 | |
|         # If you are using git, you can also automatically configure the
 | |
|         # release based on the git info.
 | |
|         "release": __version__,
 | |
|     }
 | |
|     THIRD_PARTY_APPS += ("raven.contrib.django.raven_compat",)
 | |
| 
 | |
| 
 | |
| # Apps specific for this project go here.
 | |
| LOCAL_APPS = (
 | |
|     "funkwhale_api.common",
 | |
|     "funkwhale_api.activity.apps.ActivityConfig",
 | |
|     "funkwhale_api.users",  # custom users app
 | |
|     # Your stuff: custom apps go here
 | |
|     "funkwhale_api.instance",
 | |
|     "funkwhale_api.music",
 | |
|     "funkwhale_api.requests",
 | |
|     "funkwhale_api.favorites",
 | |
|     "funkwhale_api.federation",
 | |
|     "funkwhale_api.moderation",
 | |
|     "funkwhale_api.radios",
 | |
|     "funkwhale_api.history",
 | |
|     "funkwhale_api.playlists",
 | |
|     "funkwhale_api.subsonic",
 | |
| )
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
 | |
| 
 | |
| INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
 | |
| 
 | |
| # MIDDLEWARE CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| MIDDLEWARE = (
 | |
|     "funkwhale_api.common.middleware.SPAFallbackMiddleware",
 | |
|     "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",
 | |
|     "funkwhale_api.users.middleware.RecordActivityMiddleware",
 | |
| )
 | |
| 
 | |
| # MIGRATIONS CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| MIGRATION_MODULES = {"sites": "funkwhale_api.contrib.sites.migrations"}
 | |
| 
 | |
| # 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
 | |
| FIXTURE_DIRS = (str(APPS_DIR.path("fixtures")),)
 | |
| 
 | |
| # EMAIL CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| 
 | |
| # EMAIL
 | |
| # ------------------------------------------------------------------------------
 | |
| DEFAULT_FROM_EMAIL = env(
 | |
|     "DEFAULT_FROM_EMAIL", default="Funkwhale <noreply@{}>".format(FUNKWHALE_HOSTNAME)
 | |
| )
 | |
| 
 | |
| EMAIL_SUBJECT_PREFIX = env("EMAIL_SUBJECT_PREFIX", default="[Funkwhale] ")
 | |
| SERVER_EMAIL = env("SERVER_EMAIL", default=DEFAULT_FROM_EMAIL)
 | |
| 
 | |
| 
 | |
| EMAIL_CONFIG = env.email_url("EMAIL_CONFIG", default="consolemail://")
 | |
| 
 | |
| vars().update(EMAIL_CONFIG)
 | |
| 
 | |
| # DATABASE CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
 | |
| DATABASES = {
 | |
|     # Raises ImproperlyConfigured exception if DATABASE_URL not in os.environ
 | |
|     "default": env.db("DATABASE_URL")
 | |
| }
 | |
| DATABASES["default"]["ATOMIC_REQUESTS"] = True
 | |
| #
 | |
| # 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.
 | |
| TIME_ZONE = "UTC"
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
 | |
| LANGUAGE_CODE = "en-us"
 | |
| 
 | |
| # 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
 | |
|         "BACKEND": "django.template.backends.django.DjangoTemplates",
 | |
|         # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
 | |
|         "DIRS": [str(APPS_DIR.path("templates"))],
 | |
|         "OPTIONS": {
 | |
|             # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
 | |
|             "debug": DEBUG,
 | |
|             # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
 | |
|             # https://docs.djangoproject.com/en/dev/ref/templates/api/#loader-types
 | |
|             "loaders": [
 | |
|                 "django.template.loaders.filesystem.Loader",
 | |
|                 "django.template.loaders.app_directories.Loader",
 | |
|             ],
 | |
|             # See: https://docs.djangoproject.com/en/dev/ref/settings/#template-context-processors
 | |
|             "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",
 | |
|                 # Your stuff: custom template context processors go here
 | |
|             ],
 | |
|         },
 | |
|     }
 | |
| ]
 | |
| 
 | |
| # See: http://django-crispy-forms.readthedocs.org/en/latest/install.html#template-packs
 | |
| CRISPY_TEMPLATE_PACK = "bootstrap3"
 | |
| 
 | |
| # STATIC FILE CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
 | |
| STATIC_ROOT = env("STATIC_ROOT", default=str(ROOT_DIR("staticfiles")))
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
 | |
| STATIC_URL = env("STATIC_URL", default="/staticfiles/")
 | |
| DEFAULT_FILE_STORAGE = "funkwhale_api.common.storage.ASCIIFileSystemStorage"
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#std:setting-STATICFILES_DIRS
 | |
| STATICFILES_DIRS = (str(APPS_DIR.path("static")),)
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/#staticfiles-finders
 | |
| STATICFILES_FINDERS = (
 | |
|     "django.contrib.staticfiles.finders.FileSystemFinder",
 | |
|     "django.contrib.staticfiles.finders.AppDirectoriesFinder",
 | |
| )
 | |
| 
 | |
| # MEDIA CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
 | |
| MEDIA_ROOT = env("MEDIA_ROOT", default=str(APPS_DIR("media")))
 | |
| 
 | |
| # See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
 | |
| MEDIA_URL = env("MEDIA_URL", default="/media/")
 | |
| FILE_UPLOAD_PERMISSIONS = 0o644
 | |
| # URL Configuration
 | |
| # ------------------------------------------------------------------------------
 | |
| ROOT_URLCONF = "config.urls"
 | |
| SPA_URLCONF = "config.spa_urls"
 | |
| ASGI_APPLICATION = "config.routing.application"
 | |
| 
 | |
| # This ensures that Django will be able to detect a secure connection
 | |
| SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
 | |
| 
 | |
| # AUTHENTICATION CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| AUTHENTICATION_BACKENDS = (
 | |
|     "funkwhale_api.users.auth_backends.ModelBackend",
 | |
|     "allauth.account.auth_backends.AuthenticationBackend",
 | |
| )
 | |
| SESSION_COOKIE_HTTPONLY = False
 | |
| # Some really nice defaults
 | |
| ACCOUNT_AUTHENTICATION_METHOD = "username_email"
 | |
| ACCOUNT_EMAIL_REQUIRED = True
 | |
| ACCOUNT_EMAIL_VERIFICATION = "mandatory"
 | |
| ACCOUNT_USERNAME_VALIDATORS = "funkwhale_api.users.serializers.username_validators"
 | |
| 
 | |
| # Custom user app defaults
 | |
| # Select the correct user model
 | |
| AUTH_USER_MODEL = "users.User"
 | |
| LOGIN_REDIRECT_URL = "users:redirect"
 | |
| LOGIN_URL = "account_login"
 | |
| 
 | |
| # LDAP AUTHENTICATION CONFIGURATION
 | |
| # ------------------------------------------------------------------------------
 | |
| AUTH_LDAP_ENABLED = env.bool("LDAP_ENABLED", default=False)
 | |
| if AUTH_LDAP_ENABLED:
 | |
| 
 | |
|     # Import the LDAP modules here; this way, we don't need the dependency unless someone
 | |
|     # actually enables the LDAP support
 | |
|     import ldap
 | |
|     from django_auth_ldap.config import LDAPSearch, LDAPSearchUnion, GroupOfNamesType
 | |
| 
 | |
|     # Add LDAP to the authentication backends
 | |
|     AUTHENTICATION_BACKENDS += ("django_auth_ldap.backend.LDAPBackend",)
 | |
| 
 | |
|     # Basic configuration
 | |
|     AUTH_LDAP_SERVER_URI = env("LDAP_SERVER_URI")
 | |
|     AUTH_LDAP_BIND_DN = env("LDAP_BIND_DN", default="")
 | |
|     AUTH_LDAP_BIND_PASSWORD = env("LDAP_BIND_PASSWORD", default="")
 | |
|     AUTH_LDAP_SEARCH_FILTER = env("LDAP_SEARCH_FILTER", default="(uid={0})").format(
 | |
|         "%(user)s"
 | |
|     )
 | |
|     AUTH_LDAP_START_TLS = env.bool("LDAP_START_TLS", default=False)
 | |
| 
 | |
|     DEFAULT_USER_ATTR_MAP = [
 | |
|         "first_name:givenName",
 | |
|         "last_name:sn",
 | |
|         "username:cn",
 | |
|         "email:mail",
 | |
|     ]
 | |
|     LDAP_USER_ATTR_MAP = env.list("LDAP_USER_ATTR_MAP", default=DEFAULT_USER_ATTR_MAP)
 | |
|     AUTH_LDAP_USER_ATTR_MAP = {}
 | |
|     for m in LDAP_USER_ATTR_MAP:
 | |
|         funkwhale_field, ldap_field = m.split(":")
 | |
|         AUTH_LDAP_USER_ATTR_MAP[funkwhale_field.strip()] = ldap_field.strip()
 | |
| 
 | |
|     # Determine root DN supporting multiple root DNs
 | |
|     AUTH_LDAP_ROOT_DN = env("LDAP_ROOT_DN")
 | |
|     AUTH_LDAP_ROOT_DN_LIST = []
 | |
|     for ROOT_DN in AUTH_LDAP_ROOT_DN.split():
 | |
|         AUTH_LDAP_ROOT_DN_LIST.append(
 | |
|             LDAPSearch(ROOT_DN, ldap.SCOPE_SUBTREE, AUTH_LDAP_SEARCH_FILTER)
 | |
|         )
 | |
|     # Search for the user in all the root DNs
 | |
|     AUTH_LDAP_USER_SEARCH = LDAPSearchUnion(*AUTH_LDAP_ROOT_DN_LIST)
 | |
| 
 | |
|     # Search for group types
 | |
|     LDAP_GROUP_DN = env("LDAP_GROUP_DN", default="")
 | |
|     if LDAP_GROUP_DN:
 | |
|         AUTH_LDAP_GROUP_DN = LDAP_GROUP_DN
 | |
|         # Get filter
 | |
|         AUTH_LDAP_GROUP_FILTER = env("LDAP_GROUP_FILER", default="")
 | |
|         # Search for the group in the specified DN
 | |
|         AUTH_LDAP_GROUP_SEARCH = LDAPSearch(
 | |
|             AUTH_LDAP_GROUP_DN, ldap.SCOPE_SUBTREE, AUTH_LDAP_GROUP_FILTER
 | |
|         )
 | |
|         AUTH_LDAP_GROUP_TYPE = GroupOfNamesType()
 | |
| 
 | |
|         # Configure basic group support
 | |
|         LDAP_REQUIRE_GROUP = env("LDAP_REQUIRE_GROUP", default="")
 | |
|         if LDAP_REQUIRE_GROUP:
 | |
|             AUTH_LDAP_REQUIRE_GROUP = LDAP_REQUIRE_GROUP
 | |
|         LDAP_DENY_GROUP = env("LDAP_DENY_GROUP", default="")
 | |
|         if LDAP_DENY_GROUP:
 | |
|             AUTH_LDAP_DENY_GROUP = LDAP_DENY_GROUP
 | |
| 
 | |
| 
 | |
| # SLUGLIFIER
 | |
| AUTOSLUG_SLUGIFY_FUNCTION = "slugify.slugify"
 | |
| 
 | |
| CACHE_DEFAULT = "redis://127.0.0.1:6379/0"
 | |
| CACHES = {
 | |
|     "default": env.cache_url("CACHE_URL", default=CACHE_DEFAULT),
 | |
|     "local": {
 | |
|         "BACKEND": "django.core.cache.backends.locmem.LocMemCache",
 | |
|         "LOCATION": "local-cache",
 | |
|     },
 | |
| }
 | |
| 
 | |
| CACHES["default"]["BACKEND"] = "django_redis.cache.RedisCache"
 | |
| 
 | |
| CHANNEL_LAYERS = {
 | |
|     "default": {
 | |
|         "BACKEND": "channels_redis.core.RedisChannelLayer",
 | |
|         "CONFIG": {"hosts": [CACHES["default"]["LOCATION"]]},
 | |
|     }
 | |
| }
 | |
| 
 | |
| CACHES["default"]["OPTIONS"] = {
 | |
|     "CLIENT_CLASS": "django_redis.client.DefaultClient",
 | |
|     "IGNORE_EXCEPTIONS": True,  # mimics memcache behavior.
 | |
|     # http://niwinz.github.io/django-redis/latest/#_memcached_exceptions_behavior
 | |
| }
 | |
| 
 | |
| 
 | |
| # CELERY
 | |
| INSTALLED_APPS += ("funkwhale_api.taskapp.celery.CeleryConfig",)
 | |
| CELERY_BROKER_URL = env(
 | |
|     "CELERY_BROKER_URL", default=env("CACHE_URL", default=CACHE_DEFAULT)
 | |
| )
 | |
| # END CELERY
 | |
| # Location of root django.contrib.admin URL, use {% url 'admin:index' %}
 | |
| 
 | |
| # Your common stuff: Below this line define 3rd party library settings
 | |
| CELERY_TASK_DEFAULT_RATE_LIMIT = 1
 | |
| CELERY_TASK_TIME_LIMIT = 300
 | |
| CELERY_BEAT_SCHEDULE = {
 | |
|     "federation.clean_music_cache": {
 | |
|         "task": "federation.clean_music_cache",
 | |
|         "schedule": crontab(hour="*/2"),
 | |
|         "options": {"expires": 60 * 2},
 | |
|     },
 | |
|     "music.clean_transcoding_cache": {
 | |
|         "task": "music.clean_transcoding_cache",
 | |
|         "schedule": crontab(hour="*"),
 | |
|         "options": {"expires": 60 * 2},
 | |
|     },
 | |
| }
 | |
| 
 | |
| JWT_AUTH = {
 | |
|     "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,
 | |
| }
 | |
| OLD_PASSWORD_FIELD_ENABLED = True
 | |
| ACCOUNT_ADAPTER = "funkwhale_api.users.adapters.FunkwhaleAccountAdapter"
 | |
| CORS_ORIGIN_ALLOW_ALL = True
 | |
| # CORS_ORIGIN_WHITELIST = (
 | |
| #     'localhost',
 | |
| #     'funkwhale.localhost',
 | |
| # )
 | |
| CORS_ALLOW_CREDENTIALS = True
 | |
| 
 | |
| REST_FRAMEWORK = {
 | |
|     "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",
 | |
|     ),
 | |
|     "DEFAULT_AUTHENTICATION_CLASSES": (
 | |
|         "funkwhale_api.common.authentication.JSONWebTokenAuthenticationQS",
 | |
|         "funkwhale_api.common.authentication.BearerTokenHeaderAuth",
 | |
|         "funkwhale_api.common.authentication.JSONWebTokenAuthentication",
 | |
|         "rest_framework.authentication.SessionAuthentication",
 | |
|         "rest_framework.authentication.BasicAuthentication",
 | |
|     ),
 | |
|     "DEFAULT_FILTER_BACKENDS": (
 | |
|         "rest_framework.filters.OrderingFilter",
 | |
|         "django_filters.rest_framework.DjangoFilterBackend",
 | |
|     ),
 | |
|     "DEFAULT_RENDERER_CLASSES": ("rest_framework.renderers.JSONRenderer",),
 | |
| }
 | |
| 
 | |
| BROWSABLE_API_ENABLED = env.bool("BROWSABLE_API_ENABLED", default=False)
 | |
| if BROWSABLE_API_ENABLED:
 | |
|     REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"] += (
 | |
|         "rest_framework.renderers.BrowsableAPIRenderer",
 | |
|     )
 | |
| 
 | |
| REST_AUTH_SERIALIZERS = {
 | |
|     "PASSWORD_RESET_SERIALIZER": "funkwhale_api.users.serializers.PasswordResetSerializer"  # noqa
 | |
| }
 | |
| REST_SESSION_LOGIN = False
 | |
| REST_USE_JWT = True
 | |
| 
 | |
| ATOMIC_REQUESTS = False
 | |
| USE_X_FORWARDED_HOST = True
 | |
| USE_X_FORWARDED_PORT = True
 | |
| 
 | |
| # Wether we should use Apache, Nginx (or other) headers when serving audio files
 | |
| # Default to Nginx
 | |
| REVERSE_PROXY_TYPE = env("REVERSE_PROXY_TYPE", default="nginx")
 | |
| assert REVERSE_PROXY_TYPE in ["apache2", "nginx"], "Unsupported REVERSE_PROXY_TYPE"
 | |
| 
 | |
| # Which path will be used to process the internal redirection
 | |
| # **DO NOT** put a slash at the end
 | |
| PROTECT_FILES_PATH = env("PROTECT_FILES_PATH", default="/_protected")
 | |
| 
 | |
| 
 | |
| # use this setting to tweak for how long you want to cache
 | |
| # musicbrainz results. (value is in seconds)
 | |
| MUSICBRAINZ_CACHE_DURATION = env.int("MUSICBRAINZ_CACHE_DURATION", default=300)
 | |
| 
 | |
| # Use this setting to change the musicbrainz hostname, for instance to
 | |
| # use a mirror. The hostname can also contain a port number (so, e.g.,
 | |
| # "localhost:5000" is a valid name to set).
 | |
| MUSICBRAINZ_HOSTNAME = env("MUSICBRAINZ_HOSTNAME", default="musicbrainz.org")
 | |
| 
 | |
| # Custom Admin URL, use {% url 'admin:index' %}
 | |
| ADMIN_URL = env("DJANGO_ADMIN_URL", default="^api/admin/")
 | |
| CSRF_USE_SESSIONS = True
 | |
| SESSION_ENGINE = "django.contrib.sessions.backends.cache"
 | |
| 
 | |
| # Playlist settings
 | |
| # XXX: deprecated, see #186
 | |
| PLAYLISTS_MAX_TRACKS = env.int("PLAYLISTS_MAX_TRACKS", default=250)
 | |
| 
 | |
| ACCOUNT_USERNAME_BLACKLIST = [
 | |
|     "funkwhale",
 | |
|     "library",
 | |
|     "instance",
 | |
|     "test",
 | |
|     "status",
 | |
|     "root",
 | |
|     "admin",
 | |
|     "owner",
 | |
|     "superuser",
 | |
|     "staff",
 | |
|     "service",
 | |
|     "me",
 | |
|     "ghost",
 | |
|     "_",
 | |
|     "-",
 | |
|     "hello",
 | |
|     "contact",
 | |
|     "inbox",
 | |
|     "outbox",
 | |
|     "shared-inbox",
 | |
|     "shared_inbox",
 | |
|     "actor",
 | |
| ] + env.list("ACCOUNT_USERNAME_BLACKLIST", default=[])
 | |
| 
 | |
| EXTERNAL_REQUESTS_VERIFY_SSL = env.bool("EXTERNAL_REQUESTS_VERIFY_SSL", default=True)
 | |
| # XXX: deprecated, see #186
 | |
| API_AUTHENTICATION_REQUIRED = env.bool("API_AUTHENTICATION_REQUIRED", True)
 | |
| 
 | |
| MUSIC_DIRECTORY_PATH = env("MUSIC_DIRECTORY_PATH", default=None)
 | |
| # 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(
 | |
|     "MUSIC_DIRECTORY_SERVE_PATH", default=MUSIC_DIRECTORY_PATH
 | |
| )
 | |
| 
 | |
| USERS_INVITATION_EXPIRATION_DAYS = env.int(
 | |
|     "USERS_INVITATION_EXPIRATION_DAYS", default=14
 | |
| )
 | |
| 
 | |
| VERSATILEIMAGEFIELD_RENDITION_KEY_SETS = {
 | |
|     "square": [
 | |
|         ("original", "url"),
 | |
|         ("square_crop", "crop__400x400"),
 | |
|         ("medium_square_crop", "crop__200x200"),
 | |
|         ("small_square_crop", "crop__50x50"),
 | |
|     ]
 | |
| }
 | |
| VERSATILEIMAGEFIELD_SETTINGS = {"create_images_on_demand": False}
 | |
| RSA_KEY_SIZE = 2048
 | |
| # for performance gain in tests, since we don't need to actually create the
 | |
| # thumbnails
 | |
| CREATE_IMAGE_THUMBNAILS = env.bool("CREATE_IMAGE_THUMBNAILS", default=True)
 |