Dalai Felinto
4ef93583a2
This allows users to create tokens to be used with the API. The goal is to use those for the API that will allow users to upload new versions of an extension. The Tokens can be created/managed on the user profile. Note: The API entries that to actually use these tokens is handled separately on !138. Ref !134 Reviewed-by: Oleg-Komarov
339 lines
9.8 KiB
Python
339 lines
9.8 KiB
Python
"""Django settings for blender_extensions project.
|
|
|
|
Generated by 'django-admin startproject' using Django 4.0.6.
|
|
|
|
For more information on this file, see
|
|
https://docs.djangoproject.com/en/4.0/topics/settings/
|
|
|
|
For the full list of settings and their values, see
|
|
https://docs.djangoproject.com/en/4.0/ref/settings/
|
|
"""
|
|
|
|
from pathlib import Path
|
|
import os
|
|
import sys
|
|
|
|
import dj_database_url
|
|
|
|
TESTING = sys.argv[1:2] == ['test']
|
|
|
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
|
|
|
ADMIN_SITE_HEADER = 'Blender Extensions Admin'
|
|
|
|
# Quick-start development settings - unsuitable for production
|
|
# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/
|
|
|
|
# SECURITY WARNING: keep the secret key used in production secret!
|
|
SECRET_KEY = os.environ.get(
|
|
'SECRET_KEY',
|
|
'django-insecure-@!bx83z!nudfc3uvfmm+)n0a+ms1zz&z9jivwwj$&70&d48h2t',
|
|
)
|
|
|
|
# SECURITY WARNING: don't run with debug turned on in production!
|
|
DEBUG = bool(os.environ.get('DEBUG', True))
|
|
|
|
APPEND_SLASH = True
|
|
|
|
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', 'extensions.local').split(',')
|
|
|
|
AUTH_USER_MODEL = 'users.User'
|
|
|
|
# Application definition
|
|
|
|
INSTALLED_APPS = [
|
|
'users',
|
|
'teams',
|
|
'emails',
|
|
'releases',
|
|
'abuse',
|
|
'extensions',
|
|
'background_task',
|
|
'blender_id_oauth_client',
|
|
'common',
|
|
'files',
|
|
'loginas',
|
|
'notifications',
|
|
'pipeline',
|
|
'ratings',
|
|
'rangefilter',
|
|
'reviewers',
|
|
'stats',
|
|
'apitokens',
|
|
'taggit',
|
|
'drf_spectacular',
|
|
'drf_spectacular_sidecar',
|
|
'rest_framework',
|
|
'waffle',
|
|
'django.contrib.admin',
|
|
'django.contrib.auth',
|
|
'django.contrib.contenttypes',
|
|
'django.contrib.sessions',
|
|
'django.contrib.sites',
|
|
'django.contrib.messages',
|
|
'django.contrib.staticfiles',
|
|
'django.contrib.flatpages',
|
|
'django.contrib.humanize',
|
|
'actstream',
|
|
]
|
|
|
|
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',
|
|
'common.middleware.threadlocal.ThreadLocalMiddleware',
|
|
'django.contrib.flatpages.middleware.FlatpageFallbackMiddleware',
|
|
]
|
|
|
|
ROOT_URLCONF = 'blender_extensions.urls'
|
|
|
|
TEMPLATES = [
|
|
{
|
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
'DIRS': [
|
|
BASE_DIR / 'assets_shared' / 'src' / 'templates',
|
|
],
|
|
'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',
|
|
'loginas.context_processors.impersonated_session_status',
|
|
'common.context_processors.extra_context',
|
|
],
|
|
},
|
|
},
|
|
]
|
|
|
|
WSGI_APPLICATION = 'blender_extensions.wsgi.application'
|
|
|
|
|
|
# Database
|
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#databases
|
|
|
|
DATABASES = {
|
|
'default': dj_database_url.config(default='sqlite:///{}'.format(BASE_DIR / 'db.sqlite3')),
|
|
}
|
|
DATABASES['default']['CONN_MAX_AGE'] = None
|
|
|
|
# Password validation
|
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators
|
|
|
|
AUTH_PASSWORD_VALIDATORS = [
|
|
{
|
|
'NAME': '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/4.0/topics/i18n/
|
|
|
|
LANGUAGE_CODE = 'en-us'
|
|
|
|
TIME_ZONE = 'Europe/Amsterdam'
|
|
|
|
USE_I18N = True
|
|
|
|
USE_TZ = True
|
|
|
|
SITE_ID = 1
|
|
|
|
# Static files (CSS, JavaScript, Images)
|
|
# https://docs.djangoproject.com/en/4.0/howto/static-files/
|
|
|
|
STATIC_URL = 'static/'
|
|
MEDIA_URL = 'media/'
|
|
STATIC_ROOT = os.environ.get('STATIC_ROOT', BASE_DIR / 'public/static')
|
|
MEDIA_ROOT = os.environ.get('MEDIA_ROOT', BASE_DIR / 'public/media')
|
|
|
|
STATICFILES_DIRS = [BASE_DIR / 'assets_shared' / 'src', BASE_DIR / 'assets_shared' / 'assets']
|
|
STATICFILES_FINDERS = [
|
|
'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
'pipeline.finders.PipelineFinder',
|
|
]
|
|
STATICFILES_STORAGE = 'pipeline.storage.PipelineManifestStorage'
|
|
|
|
# Default primary key field type
|
|
# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field
|
|
|
|
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
|
|
|
LOGGING = {
|
|
'version': 1,
|
|
'disable_existing_loggers': False,
|
|
'formatters': {
|
|
'default': {'format': '%(asctime)-15s %(levelname)8s %(name)s %(message)s'},
|
|
'verbose': {
|
|
'format': (
|
|
'%(asctime)s %(levelname)8s [%(filename)s:%(lineno)d '
|
|
'%(funcName)s] %(name)s %(message)s '
|
|
),
|
|
},
|
|
},
|
|
'handlers': {
|
|
'console': {
|
|
'class': 'logging.StreamHandler',
|
|
'formatter': 'verbose',
|
|
},
|
|
},
|
|
'loggers': {
|
|
'django': {'level': 'INFO'},
|
|
},
|
|
'root': {'level': 'INFO', 'handlers': ['console']},
|
|
}
|
|
|
|
PIPELINE = {
|
|
'JS_COMPRESSOR': 'pipeline.compressors.jsmin.JSMinCompressor',
|
|
'CSS_COMPRESSOR': 'pipeline.compressors.NoopCompressor',
|
|
'JAVASCRIPT': {
|
|
'common': {
|
|
'source_filenames': (
|
|
'common/scripts/*.js',
|
|
'scripts/tutti/*.js',
|
|
),
|
|
'output_filename': 'js/common.js',
|
|
},
|
|
'extensions': {
|
|
'source_filenames': ('extensions/scripts/*.js',),
|
|
'output_filename': 'js/extensions.js',
|
|
},
|
|
},
|
|
'STYLESHEETS': {
|
|
'common': {
|
|
'source_filenames': (
|
|
'common/styles/main.sass',
|
|
'common/styles/*.scss',
|
|
),
|
|
'output_filename': 'css/common.css',
|
|
'extra_context': {'media': 'screen,projection'},
|
|
},
|
|
},
|
|
'COMPILERS': ('libsasscompiler.LibSassCompiler',),
|
|
'DISABLE_WRAPPER': True,
|
|
}
|
|
|
|
# Blender ID login and logout URLs
|
|
LOGIN_URL = '/oauth/login'
|
|
LOGOUT_URL = '/oauth/logout'
|
|
|
|
SENTRY_DSN = os.environ.get('SENTRY_DSN')
|
|
if SENTRY_DSN:
|
|
import sentry_sdk
|
|
from sentry_sdk.integrations.django import DjangoIntegration
|
|
|
|
sentry_sdk.init(
|
|
dsn=SENTRY_DSN,
|
|
integrations=[
|
|
DjangoIntegration(),
|
|
],
|
|
# Set traces_sample_rate to 1.0 to capture 100%
|
|
# of transactions for performance monitoring.
|
|
# We recommend adjusting this value in production.
|
|
traces_sample_rate=1.0,
|
|
# If you wish to associate users to errors (assuming you are using
|
|
# django.contrib.auth) you may enable sending PII data.
|
|
send_default_pii=False,
|
|
)
|
|
|
|
BLENDER_ID = {
|
|
# MUST end in a slash:
|
|
'BASE_URL': os.environ.get('BID_BASE_URL', 'http://id.local:8000/'),
|
|
'OAUTH_CLIENT': os.environ.get('BID_OAUTH_CLIENT', 'BLENDER-EXTENSIONS-DEV'),
|
|
'OAUTH_SECRET': os.environ.get(
|
|
'BID_OAUTH_SECRET', 'DEVELOPMENT-ONLY NON SECRET NEVER USE IN PRODUCTION'
|
|
),
|
|
'WEBHOOK_USER_MODIFIED_SECRET': os.environ.get(
|
|
'BID_WEBHOOK_USER_MODIFIED_SECRET', 'DEVELOPMENT-ONLY NON SECRET NEVER USE IN PRODUCTION'
|
|
),
|
|
}
|
|
|
|
TAGGIT_CASE_INSENSITIVE = True
|
|
|
|
ACTSTREAM_SETTINGS = {
|
|
'MANAGER': 'users.managers.CustomStreamManager',
|
|
'FETCH_RELATIONS': True,
|
|
}
|
|
|
|
REST_FRAMEWORK = {
|
|
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
|
|
'DEFAULT_AUTHENTICATION_CLASSES': ('apitokens.authentication.UserTokenAuthentication',),
|
|
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAuthenticated',),
|
|
}
|
|
|
|
SPECTACULAR_SETTINGS = {
|
|
'TITLE': 'Blender Extensions Platform API',
|
|
'DESCRIPTION': 'API for the Blender Extensions Platform website',
|
|
'VERSION': '1.0.0',
|
|
'SERVE_INCLUDE_SCHEMA': False,
|
|
# We use DRF sidecar so we don't rely on CDNs
|
|
'SWAGGER_UI_DIST': 'SIDECAR',
|
|
'SWAGGER_UI_FAVICON_HREF': 'SIDECAR',
|
|
'REDOC_DIST': 'SIDECAR',
|
|
}
|
|
|
|
# Fallback user for logging
|
|
SYSTEM_USER_ID = os.environ.get('SYSTEM_USER_ID', 1)
|
|
|
|
if TESTING:
|
|
# Avoid "ValueError: Missing staticfiles manifest entry for"
|
|
STATICFILES_STORAGE = 'pipeline.storage.PipelineStorage'
|
|
# Disable logging output when running tests
|
|
LOGGING = {
|
|
'version': 1,
|
|
'loggers': {
|
|
'': {
|
|
'level': 'CRITICAL',
|
|
},
|
|
},
|
|
}
|
|
|
|
if DEBUG:
|
|
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
|
|
INSTALLED_APPS.append('debug_toolbar')
|
|
MIDDLEWARE.append('debug_toolbar.middleware.DebugToolbarMiddleware')
|
|
INTERNAL_IPS = [
|
|
'127.0.0.1',
|
|
]
|
|
|
|
# Email configuration, by default uses console output
|
|
EMAIL_BACKEND = os.getenv('EMAIL_BACKEND', 'django.core.mail.backends.console.EmailBackend')
|
|
DEFAULT_REPLY_TO_EMAIL = os.getenv(
|
|
'DEFAULT_REPLY_TO_EMAIL', 'Blender Extensions Platform <extensions@blender.org>'
|
|
)
|
|
DEFAULT_FROM_EMAIL = os.getenv(
|
|
'DEFAULT_FROM_EMAIL', 'Blender Extensions Platform <extensions@blender.org>'
|
|
)
|
|
EMAIL_HOST = os.getenv('EMAIL_HOST')
|
|
EMAIL_PORT = os.getenv('EMAIL_PORT', '587')
|
|
EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER')
|
|
EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD')
|
|
|
|
ACTSTREAM_SETTINGS = {
|
|
'MANAGER': 'actstream.managers.ActionManager',
|
|
}
|
|
|
|
# Require file validation for other file processing (e.g. thumbnails).
|
|
# Should be set for staging/production.
|
|
REQUIRE_FILE_VALIDATION = os.getenv('REQUIRE_FILE_VALIDATION', False)
|
|
|
|
# Maximum number of attempts for failing background tasks
|
|
MAX_ATTEMPTS = 5
|