more configurable
This commit is contained in:
parent
605d8373bf
commit
65a2b82383
11 changed files with 186 additions and 190 deletions
2
.github/workflows/docker-dev.yml
vendored
2
.github/workflows/docker-dev.yml
vendored
|
@ -5,7 +5,7 @@ on: [push, pull_request]
|
||||||
jobs:
|
jobs:
|
||||||
push_to_docker_hub:
|
push_to_docker_hub:
|
||||||
name: build image and push to Docker Hub
|
name: build image and push to Docker Hub
|
||||||
if: github.repository_owner == 'neodb-social'
|
# if: github.repository_owner == 'neodb-social'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Check out the repo
|
- name: Check out the repo
|
||||||
|
|
|
@ -6,6 +6,149 @@ env = environ.Env(
|
||||||
# set casting, default value
|
# set casting, default value
|
||||||
DEBUG=(bool, False)
|
DEBUG=(bool, False)
|
||||||
)
|
)
|
||||||
|
# TODO: use django-environ or similar package for env parsing
|
||||||
|
|
||||||
|
# ====== USER CONFIGUTRATION START ======
|
||||||
|
|
||||||
|
# SECURITY WARNING: use your own secret key and keep it!
|
||||||
|
SECRET_KEY = os.environ.get("NEODB_SECRET_KEY", "insecure")
|
||||||
|
|
||||||
|
# SECURITY WARNING: don't run with debug turned on in production!
|
||||||
|
DEBUG = os.environ.get("NEODB_DEBUG", "") != ""
|
||||||
|
|
||||||
|
DATABASES = {
|
||||||
|
"default": {
|
||||||
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
|
"NAME": os.environ.get("NEODB_DB_NAME", "test_neodb"),
|
||||||
|
"USER": os.environ.get("NEODB_DB_USER", "testuser"),
|
||||||
|
"PASSWORD": os.environ.get("NEODB_DB_PASSWORD", "testpass"),
|
||||||
|
"HOST": os.environ.get("NEODB_DB_HOST", "127.0.0.1"),
|
||||||
|
"PORT": int(os.environ.get("NEODB_DB_PORT", 5432)),
|
||||||
|
"OPTIONS": {
|
||||||
|
"client_encoding": "UTF8",
|
||||||
|
# 'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_DEFAULT,
|
||||||
|
},
|
||||||
|
"TEST": {
|
||||||
|
"DEPENDENCIES": ["takahe"],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"takahe": {
|
||||||
|
"ENGINE": "django.db.backends.postgresql",
|
||||||
|
"NAME": os.environ.get("TAKAHE_DB_NAME", "test_neodb_takahe"),
|
||||||
|
"USER": os.environ.get("TAKAHE_DB_USER", "testuser"),
|
||||||
|
"PASSWORD": os.environ.get("TAKAHE_DB_PASSWORD", "testpass"),
|
||||||
|
"HOST": os.environ.get("TAKAHE_DB_HOST", "127.0.0.1"),
|
||||||
|
"PORT": os.environ.get("TAKAHE_DB_PORT", 15432),
|
||||||
|
"OPTIONS": {
|
||||||
|
"client_encoding": "UTF8",
|
||||||
|
# 'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_DEFAULT,
|
||||||
|
},
|
||||||
|
"TEST": {
|
||||||
|
"DEPENDENCIES": [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
REDIS_HOST = os.environ.get("NEODB_REDIS_HOST", "127.0.0.1")
|
||||||
|
REDIS_PORT = int(os.environ.get("NEODB_REDIS_PORT", 6379))
|
||||||
|
REDIS_DB = int(os.environ.get("NEODB_REDIS_DB", 0))
|
||||||
|
|
||||||
|
if os.environ.get("NEODB_TYPESENSE_ENABLE", ""):
|
||||||
|
SEARCH_BACKEND = "TYPESENSE"
|
||||||
|
|
||||||
|
SEARCH_BACKEND = None
|
||||||
|
|
||||||
|
# SEARCH_BACKEND = 'MEILISEARCH'
|
||||||
|
# MEILISEARCH_SERVER = 'http://127.0.0.1:7700'
|
||||||
|
# MEILISEARCH_KEY = 'deadbeef'
|
||||||
|
|
||||||
|
TYPESENSE_CONNECTION = {
|
||||||
|
"api_key": os.environ.get("NEODB_TYPESENSE_KEY", "insecure"),
|
||||||
|
"nodes": [
|
||||||
|
{
|
||||||
|
"host": os.environ.get("NEODB_TYPESENSE_HOST", "127.0.0.1"),
|
||||||
|
"port": os.environ.get("NEODB_TYPESENSE_PORT", "8108"),
|
||||||
|
"protocol": "http",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connection_timeout_seconds": 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
SITE_DOMAIN = os.environ.get("NEODB_SITE_DOMAIN", "nicedb.org")
|
||||||
|
SITE_INFO = {
|
||||||
|
"site_name": os.environ.get("NEODB_SITE_NAME", "NiceDB"),
|
||||||
|
"site_domain": SITE_DOMAIN,
|
||||||
|
"site_url": os.environ.get("NEODB_SITE_URL", "https://" + SITE_DOMAIN),
|
||||||
|
"site_logo": os.environ.get("NEODB_SITE_LOGO", "/s/img/logo.svg"),
|
||||||
|
"site_icon": os.environ.get("NEODB_SITE_ICON", "/s/img/logo.svg"),
|
||||||
|
"user_icon": os.environ.get("NEODB_USER_ICON", "/s/img/avatar.svg"),
|
||||||
|
"social_link": "https://donotban.com/@testie",
|
||||||
|
"support_link": "https://github.com/doubaniux/boofilsic/issues",
|
||||||
|
"donation_link": "https://patreon.com/tertius",
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_ADMIN_USERNAMES = [
|
||||||
|
u for u in os.environ.get("NEODB_ADMIN_USERNAMES", "").split(",") if u
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# Mastodon/Pleroma instance allowed to login, keep empty to allow any instance to login
|
||||||
|
MASTODON_ALLOWED_SITES = []
|
||||||
|
|
||||||
|
# Allow user to create account with email (and link to Mastodon account later)
|
||||||
|
ALLOW_EMAIL_ONLY_ACCOUNT = False
|
||||||
|
|
||||||
|
# Timeout of requests to Mastodon, in seconds
|
||||||
|
MASTODON_TIMEOUT = 30
|
||||||
|
|
||||||
|
MASTODON_CLIENT_SCOPE = "read:accounts read:follows read:search read:blocks read:mutes write:statuses write:media"
|
||||||
|
# use the following to avoid re-authorize when migrating to a future version with more features
|
||||||
|
# MASTODON_CLIENT_SCOPE = "read write follow"
|
||||||
|
|
||||||
|
# some Mastodon-compatible software like Pixelfed does not support granular scopes
|
||||||
|
MASTODON_LEGACY_CLIENT_SCOPE = "read write follow"
|
||||||
|
|
||||||
|
# Emoji code in mastodon
|
||||||
|
STAR_SOLID = ":star_solid:"
|
||||||
|
STAR_HALF = ":star_half:"
|
||||||
|
STAR_EMPTY = ":star_empty:"
|
||||||
|
|
||||||
|
DISCORD_WEBHOOKS = {"user-report": None}
|
||||||
|
|
||||||
|
# Spotify credentials
|
||||||
|
SPOTIFY_CREDENTIAL = "***REMOVED***"
|
||||||
|
|
||||||
|
# The Movie Database (TMDB) API Keys
|
||||||
|
TMDB_API3_KEY = "***REMOVED***"
|
||||||
|
# TMDB_API4_KEY = "deadbeef.deadbeef.deadbeef"
|
||||||
|
|
||||||
|
# Google Books API Key
|
||||||
|
GOOGLE_API_KEY = "***REMOVED***"
|
||||||
|
|
||||||
|
# Discogs API Key
|
||||||
|
# How to get: a personal access token from https://www.discogs.com/settings/developers
|
||||||
|
DISCOGS_API_KEY = "***REMOVED***"
|
||||||
|
|
||||||
|
# IGDB
|
||||||
|
IGDB_CLIENT_ID = "deadbeef"
|
||||||
|
IGDB_CLIENT_SECRET = ""
|
||||||
|
|
||||||
|
# List of available proxies for proxy downloader, in format of ["http://x.y:port?url=__URL__", ...]
|
||||||
|
DOWNLOADER_PROXY_LIST = [
|
||||||
|
u for u in os.environ.get("NEODB_DOWNLOADER_PROXY_LIST", "").split(",") if u
|
||||||
|
]
|
||||||
|
|
||||||
|
# Backup proxy for proxy downloader, in format of "http://xyz:port?url=__URL__"
|
||||||
|
DOWNLOADER_BACKUP_PROXY = os.environ.get("NEODB_DOWNLOADER_BACKUP_PROXY", "")
|
||||||
|
|
||||||
|
# Timeout of downloader requests, in seconds
|
||||||
|
DOWNLOADER_REQUEST_TIMEOUT = 90
|
||||||
|
# Timeout of downloader cache, in seconds
|
||||||
|
DOWNLOADER_CACHE_TIMEOUT = 300
|
||||||
|
# Number of retries of downloader, when site is using RetryDownloader
|
||||||
|
DOWNLOADER_RETRIES = 3
|
||||||
|
|
||||||
|
# ====== USER CONFIGUTRATION END ======
|
||||||
|
|
||||||
NEODB_VERSION = "0.8"
|
NEODB_VERSION = "0.8"
|
||||||
DATABASE_ROUTERS = ["takahe.db_routes.TakaheRouter"]
|
DATABASE_ROUTERS = ["takahe.db_routes.TakaheRouter"]
|
||||||
|
@ -17,16 +160,6 @@ DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
|
||||||
# for legacy deployment:
|
# for legacy deployment:
|
||||||
# DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
# DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
|
||||||
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
|
|
||||||
|
|
||||||
# SECURITY WARNING: use your own secret key and keep it!
|
|
||||||
SECRET_KEY = os.environ.get("NEODB_SECRET_KEY", "insecure")
|
|
||||||
|
|
||||||
|
|
||||||
# SECURITY WARNING: don't run with debug turned on in production!
|
|
||||||
DEBUG = os.environ.get("NEODB_DEBUG", "") != ""
|
|
||||||
|
|
||||||
ALLOWED_HOSTS = ["*"]
|
ALLOWED_HOSTS = ["*"]
|
||||||
|
|
||||||
# To allow debug in template context
|
# To allow debug in template context
|
||||||
|
@ -118,51 +251,6 @@ WSGI_APPLICATION = "boofilsic.wsgi.application"
|
||||||
|
|
||||||
SESSION_COOKIE_NAME = "neodbsid"
|
SESSION_COOKIE_NAME = "neodbsid"
|
||||||
|
|
||||||
CACHES = {
|
|
||||||
"default": {
|
|
||||||
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Database
|
|
||||||
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
|
|
||||||
|
|
||||||
DATABASES = {
|
|
||||||
"default": {
|
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
|
||||||
"NAME": os.environ.get("NEODB_DB_NAME", "test_neodb"),
|
|
||||||
"USER": os.environ.get("NEODB_DB_USER", "testuser"),
|
|
||||||
"PASSWORD": os.environ.get("NEODB_DB_PASSWORD", "testpass"),
|
|
||||||
"HOST": os.environ.get("NEODB_DB_HOST", "127.0.0.1"),
|
|
||||||
"PORT": int(os.environ.get("NEODB_DB_PORT", 5432)),
|
|
||||||
"OPTIONS": {
|
|
||||||
"client_encoding": "UTF8",
|
|
||||||
# 'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_DEFAULT,
|
|
||||||
},
|
|
||||||
"TEST": {
|
|
||||||
"DEPENDENCIES": ["takahe"],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"takahe": {
|
|
||||||
"ENGINE": "django.db.backends.postgresql",
|
|
||||||
"NAME": os.environ.get("TAKAHE_DB_NAME", "test_neodb_takahe"),
|
|
||||||
"USER": os.environ.get("TAKAHE_DB_USER", "testuser"),
|
|
||||||
"PASSWORD": os.environ.get("TAKAHE_DB_PASSWORD", "testpass"),
|
|
||||||
"HOST": os.environ.get("TAKAHE_DB_HOST", "127.0.0.1"),
|
|
||||||
"PORT": os.environ.get("TAKAHE_DB_PORT", 15432),
|
|
||||||
"OPTIONS": {
|
|
||||||
"client_encoding": "UTF8",
|
|
||||||
# 'isolation_level': psycopg2.extensions.ISOLATION_LEVEL_DEFAULT,
|
|
||||||
},
|
|
||||||
"TEST": {
|
|
||||||
"DEPENDENCIES": [],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
# Customized auth backend, glue OAuth2 and Django User model together
|
|
||||||
# https://docs.djangoproject.com/en/3.0/topics/auth/customizing/#authentication-backends
|
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = [
|
AUTHENTICATION_BACKENDS = [
|
||||||
"mastodon.auth.OAuth2Backend",
|
"mastodon.auth.OAuth2Backend",
|
||||||
"oauth2_provider.backends.OAuth2Backend",
|
"oauth2_provider.backends.OAuth2Backend",
|
||||||
|
@ -171,7 +259,6 @@ AUTHENTICATION_BACKENDS = [
|
||||||
|
|
||||||
MARKDOWNX_MARKDOWNIFY_FUNCTION = "journal.models.render_md"
|
MARKDOWNX_MARKDOWNIFY_FUNCTION = "journal.models.render_md"
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
# https://docs.djangoproject.com/en/3.0/topics/i18n/
|
||||||
|
|
||||||
|
@ -185,21 +272,19 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
|
||||||
USE_X_FORWARDED_HOST = True
|
USE_X_FORWARDED_HOST = True
|
||||||
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
SECURE_PROXY_SSL_HEADER = ("HTTP_X_FORWARDED_PROTO", "https")
|
||||||
DATA_UPLOAD_MAX_MEMORY_SIZE = 100 * 1024 * 1024
|
DATA_UPLOAD_MAX_MEMORY_SIZE = 100 * 1024 * 1024
|
||||||
CSRF_COOKIE_SECURE = True
|
CSRF_COOKIE_SECURE = True
|
||||||
SESSION_COOKIE_SECURE = True
|
SESSION_COOKIE_SECURE = True
|
||||||
|
|
||||||
if os.getenv("NEODB_SSL", "") != "":
|
if os.getenv("NEODB_SSL", "") != "":
|
||||||
|
# FIXME: remove this since user may enforce SSL in reverse proxy
|
||||||
SECURE_SSL_REDIRECT = True
|
SECURE_SSL_REDIRECT = True
|
||||||
SECURE_HSTS_PRELOAD = True
|
SECURE_HSTS_PRELOAD = True
|
||||||
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
||||||
SECURE_HSTS_SECONDS = 31536000
|
SECURE_HSTS_SECONDS = 31536000
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
|
||||||
# https://docs.djangoproject.com/en/3.0/howto/static-files/
|
|
||||||
|
|
||||||
STATIC_URL = "/s/"
|
STATIC_URL = "/s/"
|
||||||
STATIC_ROOT = os.environ.get("NEODB_STATIC_ROOT", os.path.join(BASE_DIR, "static/"))
|
STATIC_ROOT = os.environ.get("NEODB_STATIC_ROOT", os.path.join(BASE_DIR, "static/"))
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
|
@ -240,16 +325,9 @@ STORAGES = { # TODO: support S3
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
SITE_DOMAIN = os.environ.get("NEODB_SITE_DOMAIN", "nicedb.org")
|
|
||||||
SITE_INFO = {
|
# Allow user to login via any Mastodon/Pleroma sites
|
||||||
"site_name": os.environ.get("NEODB_SITE_NAME", "NiceDB"),
|
MASTODON_ALLOW_ANY_SITE = False if MASTODON_ALLOWED_SITES else True
|
||||||
"site_domain": SITE_DOMAIN,
|
|
||||||
"site_url": os.environ.get("NEODB_SITE_URL", "https://" + SITE_DOMAIN),
|
|
||||||
"support_link": "https://github.com/doubaniux/boofilsic/issues",
|
|
||||||
"social_link": "https://donotban.com/@testie",
|
|
||||||
"donation_link": "https://patreon.com/tertius",
|
|
||||||
"settings_module": os.getenv("DJANGO_SETTINGS_MODULE"),
|
|
||||||
}
|
|
||||||
|
|
||||||
REDIRECT_URIS = SITE_INFO["site_url"] + "/account/login/oauth"
|
REDIRECT_URIS = SITE_INFO["site_url"] + "/account/login/oauth"
|
||||||
# for sites migrated from previous version, either wipe mastodon client ids or use:
|
# for sites migrated from previous version, either wipe mastodon client ids or use:
|
||||||
|
@ -277,60 +355,12 @@ DEFAULT_COLLECTION_IMAGE = os.path.join(COLLECTION_MEDIA_PATH_ROOT, "default.svg
|
||||||
SYNC_FILE_PATH_ROOT = "sync/"
|
SYNC_FILE_PATH_ROOT = "sync/"
|
||||||
EXPORT_FILE_PATH_ROOT = "export/"
|
EXPORT_FILE_PATH_ROOT = "export/"
|
||||||
|
|
||||||
# Allow user to login via any Mastodon/Pleroma sites
|
|
||||||
MASTODON_ALLOW_ANY_SITE = True
|
|
||||||
|
|
||||||
# Allow user to create account with email (and link to Mastodon account later)
|
|
||||||
ALLOW_EMAIL_ONLY_ACCOUNT = False
|
|
||||||
|
|
||||||
# Timeout of requests to Mastodon, in seconds
|
|
||||||
MASTODON_TIMEOUT = 30
|
|
||||||
|
|
||||||
MASTODON_CLIENT_SCOPE = "read write follow"
|
|
||||||
# use the following if it's a new site
|
|
||||||
# MASTODON_CLIENT_SCOPE = 'read:accounts read:follows read:search read:blocks read:mutes write:statuses write:media'
|
|
||||||
|
|
||||||
MASTODON_LEGACY_CLIENT_SCOPE = "read write follow"
|
|
||||||
|
|
||||||
# Emoji code in mastodon
|
|
||||||
STAR_SOLID = ":star_solid:"
|
|
||||||
STAR_HALF = ":star_half:"
|
|
||||||
STAR_EMPTY = ":star_empty:"
|
|
||||||
|
|
||||||
# Default redirect loaction when access login required view
|
# Default redirect loaction when access login required view
|
||||||
LOGIN_URL = "/account/login"
|
LOGIN_URL = "/account/login"
|
||||||
|
|
||||||
# Admin site root url
|
# Admin site root url
|
||||||
ADMIN_URL = "tertqX7256n7ej8nbv5cwvsegdse6w7ne5rHd"
|
ADMIN_URL = "tertqX7256n7ej8nbv5cwvsegdse6w7ne5rHd"
|
||||||
|
|
||||||
SCRAPING_TIMEOUT = 90
|
|
||||||
|
|
||||||
# ScraperAPI api key
|
|
||||||
SCRAPERAPI_KEY = "***REMOVED***"
|
|
||||||
PROXYCRAWL_KEY = None
|
|
||||||
SCRAPESTACK_KEY = None
|
|
||||||
|
|
||||||
# Spotify credentials
|
|
||||||
SPOTIFY_CREDENTIAL = "***REMOVED***"
|
|
||||||
|
|
||||||
# IMDb API service https://imdb-api.com/
|
|
||||||
IMDB_API_KEY = "***REMOVED***"
|
|
||||||
|
|
||||||
# The Movie Database (TMDB) API Keys
|
|
||||||
TMDB_API3_KEY = "***REMOVED***"
|
|
||||||
# TMDB_API4_KEY = "deadbeef.deadbeef.deadbeef"
|
|
||||||
|
|
||||||
# Google Books API Key
|
|
||||||
GOOGLE_API_KEY = "***REMOVED***"
|
|
||||||
|
|
||||||
# Discogs API Key
|
|
||||||
# How to get: a personal access token from https://www.discogs.com/settings/developers
|
|
||||||
DISCOGS_API_KEY = "***REMOVED***"
|
|
||||||
|
|
||||||
# IGDB
|
|
||||||
IGDB_CLIENT_ID = "deadbeef"
|
|
||||||
IGDB_CLIENT_SECRET = ""
|
|
||||||
|
|
||||||
BLEACH_STRIP_COMMENTS = True
|
BLEACH_STRIP_COMMENTS = True
|
||||||
BLEACH_STRIP_TAGS = True
|
BLEACH_STRIP_TAGS = True
|
||||||
|
|
||||||
|
@ -349,12 +379,6 @@ THUMBNAIL_ALIASES = {
|
||||||
if DEBUG:
|
if DEBUG:
|
||||||
THUMBNAIL_DEBUG = True
|
THUMBNAIL_DEBUG = True
|
||||||
|
|
||||||
# https://django-debug-toolbar.readthedocs.io/en/latest/
|
|
||||||
# maybe benchmarking before deployment
|
|
||||||
|
|
||||||
REDIS_HOST = os.environ.get("NEODB_REDIS_HOST", "127.0.0.1")
|
|
||||||
REDIS_PORT = int(os.environ.get("NEODB_REDIS_PORT", 6379))
|
|
||||||
REDIS_DB = int(os.environ.get("NEODB_REDIS_DB", 0))
|
|
||||||
CACHES = {
|
CACHES = {
|
||||||
"default": {
|
"default": {
|
||||||
"BACKEND": "django_redis.cache.RedisCache",
|
"BACKEND": "django_redis.cache.RedisCache",
|
||||||
|
@ -379,32 +403,10 @@ RQ_SHOW_ADMIN_LINK = True
|
||||||
|
|
||||||
SEARCH_INDEX_NEW_ONLY = False
|
SEARCH_INDEX_NEW_ONLY = False
|
||||||
|
|
||||||
SEARCH_BACKEND = None
|
|
||||||
|
|
||||||
# SEARCH_BACKEND = 'MEILISEARCH'
|
|
||||||
# MEILISEARCH_SERVER = 'http://127.0.0.1:7700'
|
|
||||||
# MEILISEARCH_KEY = 'deadbeef'
|
|
||||||
|
|
||||||
if os.environ.get("NEODB_TYPESENSE_ENABLE", ""):
|
|
||||||
SEARCH_BACKEND = "TYPESENSE"
|
|
||||||
|
|
||||||
TYPESENSE_INDEX_NAME = "catalog"
|
TYPESENSE_INDEX_NAME = "catalog"
|
||||||
TYPESENSE_CONNECTION = {
|
|
||||||
"api_key": os.environ.get("NEODB_TYPESENSE_KEY", "insecure"),
|
|
||||||
"nodes": [
|
|
||||||
{
|
|
||||||
"host": os.environ.get("NEODB_TYPESENSE_HOST", "127.0.0.1"),
|
|
||||||
"port": os.environ.get("NEODB_TYPESENSE_PORT", "8108"),
|
|
||||||
"protocol": "http",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"connection_timeout_seconds": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DOWNLOADER_CACHE_TIMEOUT = 300
|
|
||||||
DOWNLOADER_RETRIES = 3
|
|
||||||
DOWNLOADER_SAVEDIR = None
|
DOWNLOADER_SAVEDIR = None
|
||||||
|
|
||||||
DISABLE_MODEL_SIGNAL = False # disable index and social feeds during importing/etc
|
DISABLE_MODEL_SIGNAL = False # disable index and social feeds during importing/etc
|
||||||
|
|
||||||
# MAINTENANCE_MODE = False
|
# MAINTENANCE_MODE = False
|
||||||
|
@ -419,9 +421,6 @@ DISABLE_MODEL_SIGNAL = False # disable index and social feeds during importing/
|
||||||
# SILKY_MAX_RESPONSE_BODY_SIZE = 1024 # If response body>1024 bytes, ignore
|
# SILKY_MAX_RESPONSE_BODY_SIZE = 1024 # If response body>1024 bytes, ignore
|
||||||
# SILKY_INTERCEPT_PERCENT = 10
|
# SILKY_INTERCEPT_PERCENT = 10
|
||||||
|
|
||||||
DISCORD_WEBHOOKS = {"user-report": None}
|
|
||||||
|
|
||||||
|
|
||||||
NINJA_PAGINATION_PER_PAGE = 20
|
NINJA_PAGINATION_PER_PAGE = 20
|
||||||
OAUTH2_PROVIDER = {
|
OAUTH2_PROVIDER = {
|
||||||
"ACCESS_TOKEN_EXPIRE_SECONDS": 3600 * 24 * 365,
|
"ACCESS_TOKEN_EXPIRE_SECONDS": 3600 * 24 * 365,
|
||||||
|
@ -430,9 +429,3 @@ OAUTH2_PROVIDER = {
|
||||||
OAUTH2_PROVIDER_APPLICATION_MODEL = "developer.Application"
|
OAUTH2_PROVIDER_APPLICATION_MODEL = "developer.Application"
|
||||||
|
|
||||||
DEVELOPER_CONSOLE_APPLICATION_CLIENT_ID = "NEODB_DEVELOPER_CONSOLE"
|
DEVELOPER_CONSOLE_APPLICATION_CLIENT_ID = "NEODB_DEVELOPER_CONSOLE"
|
||||||
|
|
||||||
SETUP_ADMIN_USERNAMES = [
|
|
||||||
u for u in os.environ.get("NEODB_ADMIN_USERNAMES", "").split(",") if u
|
|
||||||
]
|
|
||||||
|
|
||||||
SITE_INFO["site_logo"] = os.environ.get("NEODB_SITE_LOGO", "/s/img/logo.svg")
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ class BasicDownloader:
|
||||||
self.headers = headers
|
self.headers = headers
|
||||||
|
|
||||||
def get_timeout(self):
|
def get_timeout(self):
|
||||||
return settings.SCRAPING_TIMEOUT
|
return settings.DOWNLOADER_REQUEST_TIMEOUT
|
||||||
|
|
||||||
def validate_response(self, response):
|
def validate_response(self, response):
|
||||||
if response is None:
|
if response is None:
|
||||||
|
@ -191,26 +191,17 @@ class BasicDownloader:
|
||||||
|
|
||||||
class ProxiedDownloader(BasicDownloader):
|
class ProxiedDownloader(BasicDownloader):
|
||||||
def get_proxied_urls(self):
|
def get_proxied_urls(self):
|
||||||
|
if not settings.DOWNLOADER_PROXY_LIST:
|
||||||
|
return [self.url]
|
||||||
urls = []
|
urls = []
|
||||||
if settings.SCRAPESTACK_KEY is not None:
|
for p in settings.DOWNLOADER_PROXY_LIST:
|
||||||
# urls.append(f'http://api.scrapestack.com/scrape?access_key={settings.SCRAPESTACK_KEY}&url={self.url}')
|
urls.append(p.replace("__URL__", quote(self.url)))
|
||||||
urls.append(
|
|
||||||
f"http://api.scrapestack.com/scrape?keep_headers=1&access_key={settings.SCRAPESTACK_KEY}&url={quote(self.url)}"
|
|
||||||
)
|
|
||||||
if settings.PROXYCRAWL_KEY is not None:
|
|
||||||
urls.append(
|
|
||||||
f"https://api.proxycrawl.com/?token={settings.PROXYCRAWL_KEY}&url={quote(self.url)}"
|
|
||||||
)
|
|
||||||
if settings.SCRAPERAPI_KEY is not None:
|
|
||||||
urls.append(
|
|
||||||
f"http://api.scraperapi.com/?api_key={settings.SCRAPERAPI_KEY}&url={quote(self.url)}"
|
|
||||||
)
|
|
||||||
return urls
|
return urls
|
||||||
|
|
||||||
def get_special_proxied_url(self):
|
def get_special_proxied_url(self):
|
||||||
return (
|
return (
|
||||||
f"{settings.LOCAL_PROXY}?url={quote(self.url)}"
|
settings.DOWNLOADER_BACKUP_PROXY.replace("__URL__", quote(self.url))
|
||||||
if settings.LOCAL_PROXY is not None
|
if settings.DOWNLOADER_BACKUP_PROXY
|
||||||
else None
|
else None
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
<summary aria-haspopup="listbox">
|
<summary aria-haspopup="listbox">
|
||||||
<span class="avatar">
|
<span class="avatar">
|
||||||
<img alt=""
|
<img alt=""
|
||||||
src="{% if request.user.is_authenticated %}{{ request.user.avatar }}{% else %}{% static 'img/avatar.svg' %}{% endif %}" />
|
src="{% if request.user.is_authenticated %}{{ request.user.avatar }}{% else %}{{ user_icon }}{% endif %}" />
|
||||||
</span>
|
</span>
|
||||||
</summary>
|
</summary>
|
||||||
<ul role="listbox" style="min-width:-webkit-max-content;" dir="rtl">
|
<ul role="listbox" style="min-width:-webkit-max-content;" dir="rtl">
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
<link rel="icon" href="{{ site_logo }}">
|
<link rel="icon" href="{{ site_icon }}">
|
||||||
<link rel="apple-touch-icon" href="{{ site_logo }}">
|
<link rel="apple-touch-icon" href="{{ site_logo }}">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-title" content="{{ site_name }}">
|
<meta name="apple-mobile-web-app-title" content="{{ site_name }}">
|
||||||
|
|
|
@ -43,9 +43,9 @@ OK
|
||||||
Preserving test database for alias 'default'...
|
Preserving test database for alias 'default'...
|
||||||
```
|
```
|
||||||
|
|
||||||
Debug in Docker
|
Development in Docker
|
||||||
---------------
|
---------------------
|
||||||
To debug source code with `docker compose`, add `NEODB_DEBUG=True` in `.env`, and use `--profile dev` instead of `--profile production` in commands. The `dev` profile is different from `production`:
|
To run local source code with `docker compose`, add `NEODB_DEBUG=True` in `.env`, and use `--profile dev` instead of `--profile production` in commands. The `dev` profile is different from `production`:
|
||||||
|
|
||||||
- code in `NEODB_SRC` (default: .) and `TAKAHE_SRC` (default: ./neodb-takahe) will be mounted and used in the container instead of code in the image
|
- code in `NEODB_SRC` (default: .) and `TAKAHE_SRC` (default: ./neodb-takahe) will be mounted and used in the container instead of code in the image
|
||||||
- `runserver` with autoreload will be used instead of `gunicorn` for both neodb and takahe web server
|
- `runserver` with autoreload will be used instead of `gunicorn` for both neodb and takahe web server
|
||||||
|
@ -55,12 +55,12 @@ To debug source code with `docker compose`, add `NEODB_DEBUG=True` in `.env`, an
|
||||||
- there's no automatic `migration` container, but it can be triggered manually via `docker compose run dev-shell neodb-init`
|
- there's no automatic `migration` container, but it can be triggered manually via `docker compose run dev-shell neodb-init`
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
- Python virtual environments inside docker image, which are `/neodb-venv` and `/takahe-venv`, will be used by default. They can be changed to different locations with `TAKAHE_VENV` and `NEODB_VENV` if needed, usually in a case of the local code using a package not in docker venv.
|
- Python virtual environments inside docker image, which are `/neodb-venv` and `/takahe-venv`, will be used by default. They can be changed to different locations with `TAKAHE_VENV` and `NEODB_VENV` if needed, usually in a case of development code using a package not in docker venv.
|
||||||
- Some packages inside python virtual environments are platform dependent, so mount venv from macOS into the Linux container will likely not work.
|
- Some packages inside python virtual environments are platform dependent, so mount venv built by macOS host into the Linux container will likely not work.
|
||||||
- Python servers are launched as `app` user, who has no write access to anywhere except /tmp and media path, that's by design.
|
- Python servers are launched as `app` user, who has no write access to anywhere except /tmp and media path, that's by design.
|
||||||
- Database/redis used in the container cluster are not accessible outside, which is by design. Querying them can be done by either apt update/install client packages in `dev-root` or `root` container, or a modified `docker-compose.yml` with `ports` section uncommented.
|
- Database/redis used in the container cluster are not accessible outside, which is by design. Querying them can be done by either apt update/install client packages in `dev-root` or `root` container, or a modified `docker-compose.yml` with `ports` section uncommented.
|
||||||
|
|
||||||
requires `${NEODB_SRC}/.venv` and `${TAKAHE_SRC}/.venv` both ready with all the requirements installed, and python binary pointing to `/usr/local/bin/python` (because that's where python is in the docker base image).
|
To run local unit tests, use `docker compose run dev-shell neodb-manage test`
|
||||||
|
|
||||||
Applications
|
Applications
|
||||||
------------
|
------------
|
||||||
|
|
|
@ -47,7 +47,7 @@ $ sudo usermod -aG docker neouser
|
||||||
- grab `docker-compose.yml` and `neodb.env.example` from source code
|
- grab `docker-compose.yml` and `neodb.env.example` from source code
|
||||||
- rename `neodb.env.example` to `.env`
|
- rename `neodb.env.example` to `.env`
|
||||||
|
|
||||||
## Set up .env file
|
## Set up .env file and www root
|
||||||
Change essential options like `NEODB_SITE_DOMAIN` in `.env` before starting the cluster for the first time. Changing them later may have unintended consequences, please make sure they are correct before exposing the service externally.
|
Change essential options like `NEODB_SITE_DOMAIN` in `.env` before starting the cluster for the first time. Changing them later may have unintended consequences, please make sure they are correct before exposing the service externally.
|
||||||
|
|
||||||
- `NEODB_SITE_NAME` - name of your site
|
- `NEODB_SITE_NAME` - name of your site
|
||||||
|
@ -55,6 +55,8 @@ Change essential options like `NEODB_SITE_DOMAIN` in `.env` before starting the
|
||||||
- `NEODB_SECRET_KEY` - encryption key of session data
|
- `NEODB_SECRET_KEY` - encryption key of session data
|
||||||
- `NEODB_DATA` is the path to store db/media/cache, it's `../data` by default, but can be any path that's writable
|
- `NEODB_DATA` is the path to store db/media/cache, it's `../data` by default, but can be any path that's writable
|
||||||
|
|
||||||
|
Optionally, `robots.txt` and `logo.png` may be placed under `$NEODB_DATA/www-root/`.
|
||||||
|
|
||||||
See `neodb.env.example` and `configuration.md` for more options
|
See `neodb.env.example` and `configuration.md` for more options
|
||||||
|
|
||||||
## Start docker
|
## Start docker
|
||||||
|
@ -105,6 +107,10 @@ $ docker compose --profile production up -d
|
||||||
- `docker compose run shell` to run a shell into the cluster; or `docker compose run root` for root shell, and `apt` is available if extra package needed
|
- `docker compose run shell` to run a shell into the cluster; or `docker compose run root` for root shell, and `apt` is available if extra package needed
|
||||||
- see `Debug in Docker` in [development doc](development.md) for debugging tips
|
- see `Debug in Docker` in [development doc](development.md) for debugging tips
|
||||||
|
|
||||||
|
## Multiple instance
|
||||||
|
|
||||||
|
It's possible to run multiple clusters in one host server, as long as `NEODB_SITE_DOMAIN`, `NEODB_PORT` and `NEODB_DATA` are different.
|
||||||
|
|
||||||
## Scaling
|
## Scaling
|
||||||
|
|
||||||
If you are running a high-traffic instance, spin up `NEODB_WEB_WORKER_NUM`, `TAKAHE_WEB_WORKER_NUM`, `TAKAHE_STATOR_CONCURRENCY` and `TAKAHE_STATOR_CONCURRENCY_PER_MODEL` as long as your host server can handle them.
|
If you are running a high-traffic instance, spin up `NEODB_WEB_WORKER_NUM`, `TAKAHE_WEB_WORKER_NUM`, `TAKAHE_STATOR_CONCURRENCY` and `TAKAHE_STATOR_CONCURRENCY_PER_MODEL` as long as your host server can handle them.
|
||||||
|
|
|
@ -13,7 +13,7 @@ version: "3.8"
|
||||||
x-shared:
|
x-shared:
|
||||||
neodb-service: &neodb-service
|
neodb-service: &neodb-service
|
||||||
build: .
|
build: .
|
||||||
image: neodb/neodb:${NEODB_TAG:-latest}
|
image: ${NEODB_IMAGE:-neodb/neodb:latest}
|
||||||
environment:
|
environment:
|
||||||
NEODB_SITE_NAME:
|
NEODB_SITE_NAME:
|
||||||
NEODB_SITE_DOMAIN:
|
NEODB_SITE_DOMAIN:
|
||||||
|
@ -34,6 +34,8 @@ x-shared:
|
||||||
NEODB_TYPESENSE_PORT: 8108
|
NEODB_TYPESENSE_PORT: 8108
|
||||||
NEODB_TYPESENSE_KEY: eggplant
|
NEODB_TYPESENSE_KEY: eggplant
|
||||||
NEODB_FROM_EMAIL: no-reply@${NEODB_SITE_DOMAIN}
|
NEODB_FROM_EMAIL: no-reply@${NEODB_SITE_DOMAIN}
|
||||||
|
NEODB_DOWNLOADER_PROXY_LIST:
|
||||||
|
NEODB_DOWNLOADER_BACKUP_PROXY:
|
||||||
NEODB_MEDIA_ROOT: /www/m
|
NEODB_MEDIA_ROOT: /www/m
|
||||||
NEODB_VENV: /neodb-venv
|
NEODB_VENV: /neodb-venv
|
||||||
TAKAHE_DB_NAME: takahe
|
TAKAHE_DB_NAME: takahe
|
||||||
|
|
|
@ -2,15 +2,16 @@
|
||||||
|
|
||||||
# copy along with docker-compose.yml, rename it to .env
|
# copy along with docker-compose.yml, rename it to .env
|
||||||
|
|
||||||
# Change these before start the instance for the first time
|
# Change these before start the instance for the first time!!
|
||||||
NEODB_SECRET_KEY=change_me
|
NEODB_SECRET_KEY=change_me
|
||||||
NEODB_SITE_DOMAIN=example.site
|
NEODB_SITE_DOMAIN=example.site
|
||||||
|
|
||||||
# Change these
|
# Change these too
|
||||||
NEODB_SITE_NAME=Example Site
|
NEODB_SITE_NAME=Example Site
|
||||||
NEODB_SITE_LOGO=/logo.svg
|
NEODB_SITE_LOGO=/logo.png
|
||||||
|
NEODB_SITE_ICON=/icon.png
|
||||||
|
|
||||||
# HTTP port your reverse proxy should set request to
|
# HTTP port your reverse proxy should send request to
|
||||||
# NEODB_PORT=8000
|
# NEODB_PORT=8000
|
||||||
|
|
||||||
# Path to store db/media/cache/etc, must be writable
|
# Path to store db/media/cache/etc, must be writable
|
||||||
|
@ -29,4 +30,4 @@ NEODB_SITE_LOGO=/logo.svg
|
||||||
# NEODB_DEBUG=True
|
# NEODB_DEBUG=True
|
||||||
|
|
||||||
# pull NeoDB Docker image from another tag/branch
|
# pull NeoDB Docker image from another tag/branch
|
||||||
# TAG=latest
|
# NEODB_IMAGE=neodb/neodb:latest
|
||||||
|
|
|
@ -78,11 +78,12 @@ class APIdentity(models.Model):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def avatar(self):
|
def avatar(self):
|
||||||
|
print(self.takahe_identity)
|
||||||
if self.local:
|
if self.local:
|
||||||
return (
|
return (
|
||||||
self.takahe_identity.icon.url
|
self.takahe_identity.icon.url
|
||||||
if self.takahe_identity.icon
|
if self.takahe_identity.icon
|
||||||
else static("img/avatar.svg")
|
else settings.SITE_INFO["user_icon"]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
return f"/proxy/identity_icon/{self.pk}/"
|
return f"/proxy/identity_icon/{self.pk}/"
|
||||||
|
|
|
@ -186,7 +186,9 @@ class User(AbstractUser):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def avatar(self):
|
def avatar(self):
|
||||||
return self.identity.avatar if self.identity else static("img/avatar.svg")
|
return (
|
||||||
|
self.identity.avatar if self.identity else settings.SITE_INFO["user_icon"]
|
||||||
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def handler(self):
|
def handler(self):
|
||||||
|
|
Loading…
Add table
Reference in a new issue