load settings from env/.env/neodb.conf

This commit is contained in:
Your Name 2023-09-25 19:47:46 +00:00 committed by Henri Dickson
parent 0ce78d546a
commit eff92b94ed
8 changed files with 244 additions and 204 deletions

View file

@ -44,5 +44,12 @@ jobs:
run: |
pip install -r requirements.txt
- name: Run Tests
env:
NEODB_DB_URL: postgres://testuser:testpass@127.0.0.1/test_neodb
TAKAHE_DB_URL: postgres://testuser:testpass@127.0.0.1/test_neodb_takahe
NEODB_REDIS_URL: redis://127.0.0.1:6379/0
NEODB_SITE_NAME: test
NEODB_SITE_DOMAIN: test.domain
NEODB_SECRET_KEY: test
run: |
python manage.py test

View file

@ -41,8 +41,8 @@ RUN rm -rf /var/lib/apt/lists/*
COPY --from=build /neodb /neodb
WORKDIR /neodb
COPY --from=build /neodb-venv /neodb-venv
RUN /neodb-venv/bin/python3 manage.py compilescss
RUN /neodb-venv/bin/python3 manage.py collectstatic --noinput
RUN NEODB_SECRET_KEY="t" NEODB_SITE_DOMAIN="x.y" NEODB_SITE_NAME="z" /neodb-venv/bin/python3 manage.py compilescss
RUN NEODB_SECRET_KEY="t" NEODB_SITE_DOMAIN="x.y" NEODB_SITE_NAME="z" /neodb-venv/bin/python3 manage.py collectstatic --noinput
COPY --from=build /takahe /takahe
WORKDIR /takahe

View file

@ -2,116 +2,187 @@ import os
import environ
env = environ.Env(
# set casting, default value
DEBUG=(bool, False)
NEODB_VERSION = "0.8"
# Parse configuration from:
# - environment variables
# - .env file in project root directory
# - /etc/neodb.conf
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
environ.Env.read_env("/etc/neodb.conf")
environ.Env.read_env(os.path.join(BASE_DIR, ".env"))
# ====== List of user configuration variables ======
env = environ.FileAwareEnv(
# WARNING: do not run with debug mode turned on in production
NEODB_DEBUG=(bool, False),
# WARNING: must use your own key and keep it secret
NEODB_SECRET_KEY=(str),
# Site information
NEODB_SITE_NAME=(str),
NEODB_SITE_DOMAIN=(str),
NEODB_SITE_LOGO=(str, "/s/img/logo.svg"),
NEODB_SITE_ICON=(str, "/s/img/logo.svg"),
NEODB_USER_ICON=(str, "/s/img/avatar.svg"),
# Links in site footer
NEODB_SITE_LINKS=(dict, {}),
# Invite only mode
# when True: user will not be able to register unless with invite token
# (generated by `neodb-manage invite --create`)
NEODB_INVITE_ONLY=(bool, False),
# Mastodon/Pleroma instance allowed to login, keep empty to allow any instance to login
NEODB_LOGIN_MASTODON_WHITELIST=(list, []),
# DATABASE
NEODB_DB_URL=(str, "postgres://user:pass@127.0.0.1:5432/neodb"),
# Redis, for cache and job queue
NEODB_REDIS_URL=(str, "redis://127.0.0.1:6379/0"),
# Search backend, in one of these formats:
# typesense://user:insecure@127.0.0.1:8108/catalog
NEODB_SEARCH_URL=(str, ""),
# EMAIL CONFIGURATION, in one of these formats:
# "smtp://<username>:<password>@<host>:<port>"
# "smtp+tls://<username>:<password>@<host>:<port>"
# "smtp+ssl://<username>:<password>@<host>:<port>"
# "anymail://<anymail_backend_name>?<anymail_args>"
NEODB_EMAIL_URL=(str, ""),
# EMAIL FROM
NEODB_EMAIL_FROM=(str, "🧩 NeoDB <no-reply@neodb.social>"),
# ADMIN_USERS
NEODB_ADMIN_USERNAMES=(list, []),
# List of available proxies for proxy downloader, in format of http://server1?url=__URL__,http://s2?url=__URL__,...
NEODB_DOWNLOADER_PROXY_LIST=(list, []),
# Timeout of downloader requests, in seconds
NEODB_DOWNLOADER_REQUEST_TIMEOUT=(int, 90),
# Timeout of downloader cache, in seconds
NEODB_DOWNLOADER_CACHE_TIMEOUT=(int, 300),
# Number of retries of downloader, when site is using RetryDownloader
NEODB_DOWNLOADER_RETRIES=(int, 3),
# INTEGRATED TAKAHE CONFIGURATION
TAKAHE_DB_URL=(str, "postgres://takahe:takahepass@127.0.0.1:5432/takahe"),
# Spotify - https://developer.spotify.com/
SPOTIFY_API_KEY=(str, ""),
# The Movie Database (TMDB) - https://developer.themoviedb.org/
TMDB_API_V3_KEY=(str, ""),
# Google Books - https://developers.google.com/books/docs/v1/using - not used at the moment
GOOGLE_API_KEY=(str, ""),
# Discogs - personal access token from https://www.discogs.com/settings/developers
DISCOGS_API_KEY=(str, ""),
# IGDB - https://api-docs.igdb.com/
IGDB_CLIENT_ID=(str, ""),
IGDB_CLIENT_SECRET=(str, ""),
# Discord webhooks
DISCORD_WEBHOOKS=(dict, {"user-report": None}),
# Slack API token, for sending exceptions to Slack, may deprecate in future
SLACK_API_TOKEN=(str, ""),
)
# 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", "") != ""
# ====== End of user configuration variables ======
SECRET_KEY = env("NEODB_SECRET_KEY")
DEBUG = env("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": [],
},
},
"default": env.db_url("NEODB_DB_URL"),
"takahe": env.db_url("TAKAHE_DB_URL"),
}
DATABASES["default"]["OPTIONS"] = {"client_encoding": "UTF8"}
DATABASES["default"]["TEST"] = {"DEPENDENCIES": ["takahe"]}
DATABASES["takahe"]["OPTIONS"] = {"client_encoding": "UTF8"}
DATABASES["takahe"]["TEST"] = {"DEPENDENCIES": []}
CACHES = {"default": env.cache_url("NEODB_REDIS_URL")}
_parsed_redis_url = env.url("NEODB_REDIS_URL")
RQ_QUEUES = {
q: {
"HOST": _parsed_redis_url.hostname,
"PORT": _parsed_redis_url.port,
"DB": _parsed_redis_url.path[1:],
"DEFAULT_TIMEOUT": -1,
}
for q in ["mastodon", "export", "import", "fetch", "crawl", "ap"]
}
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"
_parsed_search_url = env.url("NEODB_SEARCH_URL")
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"),
TYPESENSE_CONNECTION = {}
if _parsed_search_url.scheme == "typesense":
SEARCH_BACKEND = "TYPESENSE"
TYPESENSE_CONNECTION = {
"api_key": _parsed_search_url.password,
"nodes": [
{
"host": os.environ.get("NEODB_TYPESENSE_HOST", "127.0.0.1"),
"port": os.environ.get("NEODB_TYPESENSE_PORT", "8108"),
"host": _parsed_search_url.hostname,
"port": _parsed_search_url.port,
"protocol": "http",
}
],
"connection_timeout_seconds": 2,
}
}
TYPESENSE_INDEX_NAME = _parsed_search_url.path[1:]
# elif _parsed_search_url.scheme == "meilisearch":
# SEARCH_BACKEND = 'MEILISEARCH'
# MEILISEARCH_SERVER = 'http://127.0.0.1:7700'
# MEILISEARCH_KEY = _parsed_search_url.password
SITE_DOMAIN = os.environ.get("NEODB_SITE_DOMAIN", "nicedb.org")
DEFAULT_FROM_EMAIL = env("NEODB_EMAIL_FROM")
_parsed_email_url = env.url("NEODB_EMAIL_URL")
if _parsed_email_url.scheme == "anymail":
# "anymail://<anymail_backend_name>?<anymail_args>"
# see https://anymail.dev/
from urllib import parse
EMAIL_BACKEND = _parsed_email_url.hostname
ANYMAIL = dict(parse.parse_qsl(_parsed_email_url.query))
elif _parsed_email_url.scheme:
_parsed_email_config = env.email("NEODB_EMAIL_URL")
EMAIL_TIMEOUT = 5
vars().update(_parsed_email_config)
SITE_DOMAIN = env("NEODB_SITE_DOMAIN")
SITE_INFO = {
"site_name": os.environ.get("NEODB_SITE_NAME", "NiceDB"),
"site_name": env("NEODB_SITE_NAME"),
"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",
"site_url": env("NEODB_SITE_URL", default="https://" + SITE_DOMAIN),
"site_logo": env("NEODB_SITE_LOGO"),
"site_icon": env("NEODB_SITE_ICON"),
"user_icon": env("NEODB_USER_ICON"),
"site_links": [{"title": k, "url": v} for k, v in env("NEODB_SITE_LINKS").items()],
}
SETUP_ADMIN_USERNAMES = [
u for u in os.environ.get("NEODB_ADMIN_USERNAMES", "").split(",") if u
]
SETUP_ADMIN_USERNAMES = env("NEODB_ADMIN_USERNAMES")
# True: user will not be able to register unless with invite token (generated by `neodb-manage invite --create`)
INVITE_ONLY = os.environ.get("NEODB_INVITE_ONLY", "") != ""
INVITE_ONLY = env("NEODB_INVITE_ONLY")
# By default, NeoDB will relay with relay.neodb.net so that public user ratings/etc can be shared across instances
# If you are running a development server, set this to True to disable this behavior
DISABLE_DEFAULT_RELAY = (
os.environ.get("NEODB_DISABLE_DEFAULT_RELAY", "1" if DEBUG else "") != ""
)
DISABLE_DEFAULT_RELAY = env("NEODB_DISABLE_DEFAULT_RELAY", default=DEBUG)
# Mastodon/Pleroma instance allowed to login, keep empty to allow any instance to login
MASTODON_ALLOWED_SITES = []
MASTODON_ALLOWED_SITES = env("NEODB_LOGIN_MASTODON_WHITELIST")
# Allow user to create account with email (and link to Mastodon account later)
ALLOW_EMAIL_ONLY_ACCOUNT = False
ALLOW_EMAIL_ONLY_ACCOUNT = env.bool(
"NEODB_LOGIN_ENABLE_EMAIL_ONLY",
default=(_parsed_email_url.scheme and len(MASTODON_ALLOWED_SITES) == 0), # type: ignore
)
# Allow user to login via any Mastodon/Pleroma sites
MASTODON_ALLOW_ANY_SITE = len(MASTODON_ALLOWED_SITES) == 0
REDIRECT_URIS = env(
"NEODB_LOGIN_MASTODON_REDIRECT_URI",
default=SITE_INFO["site_url"] + "/account/login/oauth",
)
# for sites migrated from previous version, either wipe mastodon client ids or use:
# REDIRECT_URIS = f'{SITE_INFO["site_url"]}/users/OAuth2_login/'
# Timeout of requests to Mastodon, in seconds
MASTODON_TIMEOUT = 30
MASTODON_TIMEOUT = env("NEODB_LOGIN_MASTODON_TIMEOUT", default=10) # type: ignore
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"
# Scope when creating Mastodon apps
# Alternatively, use "read write follow" to avoid re-authorize when migrating to a future version with more features
MASTODON_CLIENT_SCOPE = env(
"NEODB_MASTODON_CLIENT_SCOPE",
default="read:accounts read:follows read:search read:blocks read:mutes write:statuses write:media", # type: ignore
)
# some Mastodon-compatible software like Pixelfed does not support granular scopes
MASTODON_LEGACY_CLIENT_SCOPE = "read write follow"
@ -121,49 +192,27 @@ STAR_SOLID = ":star_solid:"
STAR_HALF = ":star_half:"
STAR_EMPTY = ":star_empty:"
DISCORD_WEBHOOKS = {"user-report": None}
DISCORD_WEBHOOKS = env("DISCORD_WEBHOOKS")
SPOTIFY_CREDENTIAL = env("SPOTIFY_API_KEY")
TMDB_API3_KEY = env("TMDB_API_V3_KEY")
# TMDB_API4_KEY = env('TMDB_API_V4_KEY')
# GOOGLE_API_KEY = env('GOOGLE_API_KEY')
DISCOGS_API_KEY = env("DISCOGS_API_KEY")
IGDB_CLIENT_ID = env("IGDB_CLIENT_ID")
IGDB_CLIENT_SECRET = env("IGDB_CLIENT_SECRET")
SLACK_TOKEN = env("SLACK_API_TOKEN")
SLACK_CHANNEL = "alert"
# 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
DOWNLOADER_PROXY_LIST = env("NEODB_DOWNLOADER_PROXY_LIST")
DOWNLOADER_BACKUP_PROXY = env("NEODB_DOWNLOADER_BACKUP_PROXY", default="") # type: ignore
DOWNLOADER_REQUEST_TIMEOUT = env("NEODB_DOWNLOADER_REQUEST_TIMEOUT")
DOWNLOADER_CACHE_TIMEOUT = env("NEODB_DOWNLOADER_CACHE_TIMEOUT")
DOWNLOADER_RETRIES = env("NEODB_DOWNLOADER_RETRIES")
# ====== USER CONFIGUTRATION END ======
NEODB_VERSION = "0.8"
DATABASE_ROUTERS = ["takahe.db_routes.TakaheRouter"]
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
# for legacy deployment:
# DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
@ -198,7 +247,7 @@ INSTALLED_APPS = [
"polymorphic",
"easy_thumbnails",
"user_messages",
# "anymail",
"anymail",
# "silk",
]
@ -264,6 +313,26 @@ AUTHENTICATION_BACKENDS = [
"oauth2_provider.backends.OAuth2Backend",
]
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {"class": "logging.StreamHandler"},
},
"loggers": {
"": {
"handlers": ["console"],
"level": env("NEODB_LOG_LEVEL", default="DEBUG" if DEBUG else "INFO"), # type: ignore
},
},
}
if SLACK_TOKEN:
LOGGING["handlers"]["slack"] = {
"level": "ERROR",
"class": "django_slack.log.SlackExceptionHandler",
}
LOGGING["loggers"]["django"] = {"handlers": ["slack"], "level": "ERROR"}
MARKDOWNX_MARKDOWNIFY_FUNCTION = "journal.models.render_md"
@ -272,7 +341,7 @@ MARKDOWNX_MARKDOWNIFY_FUNCTION = "journal.models.render_md"
LANGUAGE_CODE = "zh-hans"
TIME_ZONE = "Asia/Shanghai"
TIME_ZONE = env("NEODB_TIMEZONE", default="Asia/Shanghai") # type: ignore
USE_I18N = True
@ -286,7 +355,7 @@ DATA_UPLOAD_MAX_MEMORY_SIZE = 100 * 1024 * 1024
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
if os.getenv("NEODB_SSL", "") != "":
if env("NEODB_SSL", default="") != "": # type: ignore
# FIXME: remove this since user may enforce SSL in reverse proxy
SECURE_SSL_REDIRECT = True
SECURE_HSTS_PRELOAD = True
@ -294,7 +363,8 @@ if os.getenv("NEODB_SSL", "") != "":
SECURE_HSTS_SECONDS = 31536000
STATIC_URL = "/s/"
STATIC_ROOT = os.environ.get("NEODB_STATIC_ROOT", os.path.join(BASE_DIR, "static/"))
STATIC_ROOT = env("NEODB_STATIC_ROOT", default=os.path.join(BASE_DIR, "static/")) # type: ignore
if DEBUG:
# django-sass-processor will generate neodb.css on-the-fly when DEBUG
# NEODB_STATIC_ROOT is readonly in docker mode, so we give it a writable place
@ -314,10 +384,12 @@ SILENCED_SYSTEM_CHECKS = [
"fields.W344", # Required by takahe: identical table name in different database
]
TAKAHE_MEDIA_URL = os.environ.get("TAKAHE_MEDIA_URL", "/media/")
TAKAHE_MEDIA_ROOT = os.environ.get("TAKAHE_MEDIA_ROOT", "media")
MEDIA_URL = "/m/"
MEDIA_ROOT = os.environ.get("NEODB_MEDIA_ROOT", os.path.join(BASE_DIR, "media"))
MEDIA_ROOT = env("NEODB_MEDIA_ROOT", default=os.path.join(BASE_DIR, "media")) # type: ignore
TAKAHE_MEDIA_URL = env("TAKAHE_MEDIA_URL", default="/media/") # type: ignore
TAKAHE_MEDIA_ROOT = env("TAKAHE_MEDIA_ROOT", default="media") # type: ignore
STORAGES = { # TODO: support S3
"default": {
"BACKEND": "django.core.files.storage.FileSystemStorage",
@ -334,13 +406,6 @@ STORAGES = { # TODO: support S3
},
}
# Allow user to login via any Mastodon/Pleroma sites
MASTODON_ALLOW_ANY_SITE = False if MASTODON_ALLOWED_SITES else True
REDIRECT_URIS = SITE_INFO["site_url"] + "/account/login/oauth"
# for sites migrated from previous version, either wipe mastodon client ids or use:
# REDIRECT_URIS = f'{SITE_INFO["site_url"]}/users/OAuth2_login/'
CSRF_TRUSTED_ORIGINS = [SITE_INFO["site_url"]]
if DEBUG:
CSRF_TRUSTED_ORIGINS += ["http://127.0.0.1:8000", "http://localhost:8000"]
@ -366,8 +431,8 @@ EXPORT_FILE_PATH_ROOT = "export/"
# Default redirect loaction when access login required view
LOGIN_URL = "/account/login"
# Admin site root url
ADMIN_URL = "tertqX7256n7ej8nbv5cwvsegdse6w7ne5rHd"
ADMIN_ENABLED = DEBUG
ADMIN_URL = "neodb-admin"
BLEACH_STRIP_COMMENTS = True
BLEACH_STRIP_TAGS = True
@ -384,36 +449,15 @@ THUMBNAIL_ALIASES = {
},
}
# THUMBNAIL_PRESERVE_EXTENSIONS = ('svg',)
if DEBUG:
THUMBNAIL_DEBUG = True
THUMBNAIL_DEBUG = DEBUG
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": f"redis://{REDIS_HOST}:{REDIS_PORT}/{REDIS_DB}",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
},
}
}
DJANGO_REDIS_IGNORE_EXCEPTIONS = not DEBUG
RQ_QUEUES = {
q: {
"HOST": REDIS_HOST,
"PORT": REDIS_PORT,
"DB": REDIS_DB,
"DEFAULT_TIMEOUT": -1,
}
for q in ["mastodon", "export", "import", "fetch", "crawl", "ap"]
}
RQ_SHOW_ADMIN_LINK = True
RQ_SHOW_ADMIN_LINK = DEBUG
SEARCH_INDEX_NEW_ONLY = False
TYPESENSE_INDEX_NAME = "catalog"
DOWNLOADER_SAVEDIR = None
DOWNLOADER_SAVEDIR = env("NEODB_DOWNLOADER_SAVE_DIR", default=None) # type: ignore
DISABLE_MODEL_SIGNAL = False # disable index and social feeds during importing/etc

View file

@ -1,24 +1,12 @@
<footer class="footer">
<hr>
<div class="grid">
{% if social_link %}
{% for link in site_links %}
<a class="footer__link"
target="_blank"
rel="noopener"
href="{{ social_link }}">关注我们</a>
{% endif %}
{% if support_link %}
<a class="footer__link"
target="_blank"
rel="noopener"
href="{{ support_link }}">问题反馈</a>
{% endif %}
{% if donation_link %}
<a class="footer__link"
target="_blank"
rel="noopener"
href="{{ donation_link }}">捐助本站</a>
{% endif %}
href="{{ link.url }}">{{ link.title }}</a>
{% endfor %}
<a class="footer__link" href="{% url 'management:list' %}">公告栏</a>
<a class="footer__link" href="{% url 'oauth2_provider:developer' %}">应用开发</a>
<a class="footer__link"

View file

@ -15,36 +15,31 @@ x-shared:
build: .
image: ${NEODB_IMAGE:-neodb/neodb:latest}
environment:
NEODB_DEBUG:
NEODB_SECRET_KEY:
NEODB_SITE_NAME:
NEODB_SITE_DOMAIN:
NEODB_SITE_LOGO:
NEODB_DEBUG:
NEODB_SECRET_KEY:
NEODB_SITE_ICON:
NEODB_USER_ICON:
NEODB_SITE_LINKS:
NEODB_ADMIN_USERNAMES:
NEODB_INVITE_ONLY:
NEODB_LOGIN_ENABLE_EMAIL_ONLY:
NEODB_LOGIN_MASTODON_WHITELIST:
NEODB_MASTODON_CLIENT_SCOPE:
NEODB_DISABLE_DEFAULT_RELAY:
NEODB_DB_NAME: neodb
NEODB_DB_USER: neodb
NEODB_DB_PASSWORD: aubergine
NEODB_DB_HOST: neodb-db
NEODB_DB_PORT: 5432
NEODB_REDIS_HOST: redis
NEODB_REDIS_PORT: 6379
NEODB_REDIS_DB: 0
NEODB_TYPESENSE_ENABLE: 1
NEODB_TYPESENSE_HOST: typesense
NEODB_TYPESENSE_PORT: 8108
NEODB_TYPESENSE_KEY: eggplant
NEODB_DB_URL: postgres://neodb:aubergine@neodb-db/neodb
TAKAHE_DB_URL: postgres://takahe:aubergine@takahe-db/takahe
NEODB_REDIS_URL: redis://redis:6379/0
NEODB_SEARCH_URL: typesense://user:eggplant@typesense:8108/catalog
NEODB_EMAIL_URL:
NEODB_FROM_EMAIL: no-reply@${NEODB_SITE_DOMAIN}
NEODB_DOWNLOADER_PROXY_LIST:
NEODB_DOWNLOADER_BACKUP_PROXY:
NEODB_DOWNLOADER_SAVE_DIR:
NEODB_MEDIA_ROOT: /www/m
NEODB_VENV: /neodb-venv
TAKAHE_DB_NAME: takahe
TAKAHE_DB_USER: takahe
TAKAHE_DB_PASSWORD: aubergine
TAKAHE_DB_HOST: takahe-db
TAKAHE_DB_PORT: 5432
TAKAHE_SECRET_KEY: ${NEODB_SECRET_KEY}
TAKAHE_MAIN_DOMAIN: ${NEODB_SITE_DOMAIN}
TAKAHE_MEDIA_URL: https://${NEODB_SITE_DOMAIN}/media/
@ -58,6 +53,14 @@ x-shared:
TAKAHE_STATOR_CONCURRENCY_PER_MODEL: 2
TAKAHE_DEBUG: ${NEODB_DEBUG:-False}
TAKAHE_VENV: /takahe-venv
SPOTIFY_API_KEY:
TMDB_API_V3_KEY:
GOOGLE_API_KEY:
DISCOGS_API_KEY:
IGDB_CLIENT_ID:
IGDB_CLIENT_SECRET:
DISCORD_WEBHOOKS:
SLACK_API_TOKEN:
restart: "on-failure"
volumes:
- ${NEODB_DATA:-../data}/neodb-media:/www/m

View file

@ -10,6 +10,7 @@ NEODB_SITE_DOMAIN=example.site
NEODB_SITE_NAME=Example Site
NEODB_SITE_LOGO=/logo.png
NEODB_SITE_ICON=/icon.png
NEODB_SITE_LINKS=关注NiceDB=https://donotban.com/@testie,关注NeoDB=https://mastodon.social/@neodb
# HTTP port your reverse proxy should send request to
# NEODB_PORT=8000

View file

@ -78,7 +78,6 @@ class APIdentity(models.Model):
@property
def avatar(self):
print(self.takahe_identity)
if self.local:
return (
self.takahe_identity.icon.url

View file

@ -133,9 +133,7 @@
</script>
{% else %}
<select name="domain">
{% for site in sites %}
<option value="{{ site.domain_name }}" data-client-id="{{ site.client_id }}">@{{ site.domain_name }}</option>
{% endfor %}
{% for site in sites %}<option value="{{ site }}">@{{ site }}</option>{% endfor %}
</select>
<input type='submit' value="{% trans '授权登录' %}" id="loginButton" />
{% endif %}