mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2025-05-09 12:21:57 -04:00
expose more django server config options
This commit is contained in:
parent
d016f1efb5
commit
3c3b2ee621
8 changed files with 89 additions and 37 deletions
|
@ -44,10 +44,19 @@ CONFIG_DEFAULTS: Dict[str, ConfigDefaultDict] = {
|
||||||
'TIMEOUT': {'type': int, 'default': 60},
|
'TIMEOUT': {'type': int, 'default': 60},
|
||||||
'MEDIA_TIMEOUT': {'type': int, 'default': 3600},
|
'MEDIA_TIMEOUT': {'type': int, 'default': 3600},
|
||||||
'OUTPUT_PERMISSIONS': {'type': str, 'default': '755'},
|
'OUTPUT_PERMISSIONS': {'type': str, 'default': '755'},
|
||||||
'FOOTER_INFO': {'type': str, 'default': 'Content is hosted for personal archiving purposes only. Contact server owner for any takedown requests.'},
|
|
||||||
'URL_BLACKLIST': {'type': str, 'default': None},
|
'URL_BLACKLIST': {'type': str, 'default': None},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'SERVER_CONFIG': {
|
||||||
|
'SECRET_KEY': {'type': str, 'default': None},
|
||||||
|
'ALLOWED_HOSTS': {'type': str, 'default': '*'},
|
||||||
|
'DEBUG': {'type': bool, 'default': False},
|
||||||
|
'PUBLIC_INDEX': {'type': bool, 'default': True},
|
||||||
|
'PUBLIC_SNAPSHOTS': {'type': bool, 'default': True},
|
||||||
|
'FOOTER_INFO': {'type': str, 'default': 'Content is hosted for personal archiving purposes only. Contact server owner for any takedown requests.'},
|
||||||
|
'ACTIVE_THEME': {'type': str, 'default': 'default'},
|
||||||
|
},
|
||||||
|
|
||||||
'ARCHIVE_METHOD_TOGGLES': {
|
'ARCHIVE_METHOD_TOGGLES': {
|
||||||
'SAVE_TITLE': {'type': bool, 'default': True, 'aliases': ('FETCH_TITLE',)},
|
'SAVE_TITLE': {'type': bool, 'default': True, 'aliases': ('FETCH_TITLE',)},
|
||||||
'SAVE_FAVICON': {'type': bool, 'default': True, 'aliases': ('FETCH_FAVICON',)},
|
'SAVE_FAVICON': {'type': bool, 'default': True, 'aliases': ('FETCH_FAVICON',)},
|
||||||
|
@ -313,9 +322,6 @@ def write_config_file(config: Dict[str, str], out_dir: str=None) -> ConfigDict:
|
||||||
with open(config_path, 'w+') as f:
|
with open(config_path, 'w+') as f:
|
||||||
f.write(CONFIG_HEADER)
|
f.write(CONFIG_HEADER)
|
||||||
|
|
||||||
if not config:
|
|
||||||
return {}
|
|
||||||
|
|
||||||
config_file = ConfigParser()
|
config_file = ConfigParser()
|
||||||
config_file.optionxform = str
|
config_file.optionxform = str
|
||||||
config_file.read(config_path)
|
config_file.read(config_path)
|
||||||
|
@ -336,6 +342,21 @@ def write_config_file(config: Dict[str, str], out_dir: str=None) -> ConfigDict:
|
||||||
|
|
||||||
config_file[section] = {**existing_config, key: val}
|
config_file[section] = {**existing_config, key: val}
|
||||||
|
|
||||||
|
# always make sure there's a SECRET_KEY defined for Django
|
||||||
|
existing_secret_key = None
|
||||||
|
if 'SERVER_CONFIG' in config_file and 'SECRET_KEY' in config_file['SERVER_CONFIG']:
|
||||||
|
existing_secret_key = config_file['SERVER_CONFIG']['SECRET_KEY']
|
||||||
|
|
||||||
|
if (not existing_secret_key) or ('not a valid secret' in existing_secret_key):
|
||||||
|
from django.utils.crypto import get_random_string
|
||||||
|
chars = 'abcdefghijklmnopqrstuvwxyz0123456789-_+!.'
|
||||||
|
random_secret_key = get_random_string(50, chars)
|
||||||
|
if 'SERVER_CONFIG' in config_file:
|
||||||
|
config_file['SERVER_CONFIG']['SECRET_KEY'] = random_secret_key
|
||||||
|
else:
|
||||||
|
config_file['SERVER_CONFIG'] = {'SECRET_KEY': random_secret_key}
|
||||||
|
|
||||||
|
f.write(CONFIG_HEADER)
|
||||||
config_file.write(f)
|
config_file.write(f)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -22,9 +22,16 @@ class ConfigDict(BaseConfig, total=False):
|
||||||
TIMEOUT: int
|
TIMEOUT: int
|
||||||
MEDIA_TIMEOUT: int
|
MEDIA_TIMEOUT: int
|
||||||
OUTPUT_PERMISSIONS: str
|
OUTPUT_PERMISSIONS: str
|
||||||
FOOTER_INFO: str
|
|
||||||
URL_BLACKLIST: Optional[str]
|
URL_BLACKLIST: Optional[str]
|
||||||
|
|
||||||
|
SECRET_KEY: str
|
||||||
|
ALLOWED_HOSTS: str
|
||||||
|
DEBUG: bool
|
||||||
|
PUBLIC_INDEX: bool
|
||||||
|
PUBLIC_SNAPSHOTS: bool
|
||||||
|
FOOTER_INFO: str
|
||||||
|
ACTIVE_THEME: str
|
||||||
|
|
||||||
SAVE_TITLE: bool
|
SAVE_TITLE: bool
|
||||||
SAVE_FAVICON: bool
|
SAVE_FAVICON: bool
|
||||||
SAVE_WGET: bool
|
SAVE_WGET: bool
|
||||||
|
|
|
@ -3,26 +3,25 @@ __package__ = 'archivebox.core'
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
SECRET_KEY = '---------------- not a valid secret key ! ----------------'
|
|
||||||
DEBUG = os.getenv('DEBUG', 'False').lower() == 'true'
|
|
||||||
ALLOWED_HOSTS = ['*']
|
|
||||||
|
|
||||||
REPO_DIR = os.path.abspath(os.path.join(os.path.abspath(__file__), os.path.pardir, os.path.pardir))
|
from ..config import (
|
||||||
OUTPUT_DIR = os.path.abspath(os.getenv('OUTPUT_DIR', os.curdir))
|
OUTPUT_DIR,
|
||||||
ARCHIVE_DIR = os.path.join(OUTPUT_DIR, 'archive')
|
SECRET_KEY,
|
||||||
DATABASE_FILE = os.path.join(OUTPUT_DIR, 'index.sqlite3')
|
DEBUG,
|
||||||
|
ALLOWED_HOSTS,
|
||||||
|
PYTHON_DIR,
|
||||||
|
ACTIVE_THEME,
|
||||||
|
SQL_INDEX_FILENAME,
|
||||||
|
)
|
||||||
|
|
||||||
ACTIVE_THEME = 'default'
|
|
||||||
|
|
||||||
|
ALLOWED_HOSTS = ALLOWED_HOSTS.split(',')
|
||||||
IS_SHELL = 'shell' in sys.argv[:3] or 'shell_plus' in sys.argv[:3]
|
IS_SHELL = 'shell' in sys.argv[:3] or 'shell_plus' in sys.argv[:3]
|
||||||
|
|
||||||
APPEND_SLASH = True
|
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
# 'django.contrib.sites',
|
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
@ -40,17 +39,17 @@ MIDDLEWARE = [
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'core.urls'
|
ROOT_URLCONF = 'core.urls'
|
||||||
|
APPEND_SLASH = True
|
||||||
TEMPLATES = [
|
TEMPLATES = [
|
||||||
{
|
{
|
||||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||||
'DIRS': [
|
'DIRS': [
|
||||||
os.path.join(REPO_DIR, 'themes', ACTIVE_THEME),
|
os.path.join(PYTHON_DIR, 'themes', ACTIVE_THEME),
|
||||||
os.path.join(REPO_DIR, 'themes', 'default'),
|
os.path.join(PYTHON_DIR, 'themes', 'default'),
|
||||||
os.path.join(REPO_DIR, 'themes'),
|
os.path.join(PYTHON_DIR, 'themes'),
|
||||||
],
|
],
|
||||||
'APP_DIRS': True,
|
'APP_DIRS': True,
|
||||||
'OPTIONS': {
|
'OPTIONS': {
|
||||||
|
@ -69,7 +68,7 @@ WSGI_APPLICATION = 'core.wsgi.application'
|
||||||
DATABASES = {
|
DATABASES = {
|
||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': DATABASE_FILE,
|
'NAME': os.path.join(OUTPUT_DIR, SQL_INDEX_FILENAME),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,7 +103,7 @@ SHELL_PLUS_PRINT_SQL = False
|
||||||
IPYTHON_ARGUMENTS = ['--no-confirm-exit', '--no-banner']
|
IPYTHON_ARGUMENTS = ['--no-confirm-exit', '--no-banner']
|
||||||
IPYTHON_KERNEL_DISPLAY_NAME = 'ArchiveBox Django Shell'
|
IPYTHON_KERNEL_DISPLAY_NAME = 'ArchiveBox Django Shell'
|
||||||
if IS_SHELL:
|
if IS_SHELL:
|
||||||
os.environ['PYTHONSTARTUP'] = os.path.join(REPO_DIR, 'core', 'welcome_message.py')
|
os.environ['PYTHONSTARTUP'] = os.path.join(PYTHON_DIR, 'core', 'welcome_message.py')
|
||||||
|
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'en-us'
|
||||||
|
@ -118,11 +117,7 @@ EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
|
||||||
|
|
||||||
STATIC_URL = '/static/'
|
STATIC_URL = '/static/'
|
||||||
STATICFILES_DIRS = [
|
STATICFILES_DIRS = [
|
||||||
os.path.join(REPO_DIR, 'themes', ACTIVE_THEME, 'static'),
|
os.path.join(PYTHON_DIR, 'themes', ACTIVE_THEME, 'static'),
|
||||||
os.path.join(REPO_DIR, 'themes', 'default', 'static'),
|
os.path.join(PYTHON_DIR, 'themes', 'default', 'static'),
|
||||||
os.path.join(REPO_DIR, 'themes', 'static'),
|
os.path.join(PYTHON_DIR, 'themes', 'static'),
|
||||||
]
|
]
|
||||||
|
|
||||||
SERVE_STATIC = True
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,14 @@ urlpatterns = [
|
||||||
path('add/', AddLinks.as_view(), name='AddLinks'),
|
path('add/', AddLinks.as_view(), name='AddLinks'),
|
||||||
|
|
||||||
path('static/<path>', views.serve),
|
path('static/<path>', views.serve),
|
||||||
|
|
||||||
|
path('accounts/login/', RedirectView.as_view(url='/admin/login/')),
|
||||||
|
path('accounts/logout/', RedirectView.as_view(url='/admin/logout/')),
|
||||||
|
|
||||||
path('accounts/', include('django.contrib.auth.urls')),
|
path('accounts/', include('django.contrib.auth.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
|
||||||
|
|
||||||
path('', MainIndex.as_view(), name='Home'),
|
path('', MainIndex.as_view(), name='Home'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,18 @@ from django.shortcuts import render, redirect
|
||||||
|
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.views import View, static
|
from django.views import View, static
|
||||||
|
from django.conf import settings
|
||||||
|
|
||||||
from core.models import Snapshot
|
from core.models import Snapshot
|
||||||
|
|
||||||
from ..index import load_main_index, load_main_index_meta
|
from ..index import load_main_index, load_main_index_meta
|
||||||
from ..config import OUTPUT_DIR, VERSION, FOOTER_INFO
|
from ..config import (
|
||||||
|
OUTPUT_DIR,
|
||||||
|
VERSION,
|
||||||
|
FOOTER_INFO,
|
||||||
|
PUBLIC_INDEX,
|
||||||
|
PUBLIC_SNAPSHOTS,
|
||||||
|
)
|
||||||
from ..util import base_url
|
from ..util import base_url
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,6 +23,9 @@ class MainIndex(View):
|
||||||
template = 'main_index.html'
|
template = 'main_index.html'
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
if not request.user.is_authenticated and not PUBLIC_INDEX:
|
||||||
|
return redirect(f'/admin/login/?next={request.path}')
|
||||||
|
|
||||||
all_links = load_main_index(out_dir=OUTPUT_DIR)
|
all_links = load_main_index(out_dir=OUTPUT_DIR)
|
||||||
meta_info = load_main_index_meta(out_dir=OUTPUT_DIR)
|
meta_info = load_main_index_meta(out_dir=OUTPUT_DIR)
|
||||||
|
|
||||||
|
@ -34,6 +44,9 @@ class AddLinks(View):
|
||||||
template = 'add_links.html'
|
template = 'add_links.html'
|
||||||
|
|
||||||
def get(self, request):
|
def get(self, request):
|
||||||
|
if not request.user.is_authenticated and not PUBLIC_INDEX:
|
||||||
|
return redirect(f'/admin/login/?next={request.path}')
|
||||||
|
|
||||||
context = {}
|
context = {}
|
||||||
|
|
||||||
return render(template_name=self.template, request=request, context=context)
|
return render(template_name=self.template, request=request, context=context)
|
||||||
|
@ -54,6 +67,9 @@ class LinkDetails(View):
|
||||||
if '/' not in path:
|
if '/' not in path:
|
||||||
return redirect(f'{path}/index.html')
|
return redirect(f'{path}/index.html')
|
||||||
|
|
||||||
|
if not request.user.is_authenticated and not PUBLIC_SNAPSHOTS:
|
||||||
|
return redirect(f'/admin/login/?next={request.path}')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
slug, archivefile = path.split('/', 1)
|
slug, archivefile = path.split('/', 1)
|
||||||
except (IndexError, ValueError):
|
except (IndexError, ValueError):
|
||||||
|
|
|
@ -292,14 +292,14 @@ def init(force: bool=False, out_dir: str=OUTPUT_DIR) -> None:
|
||||||
|
|
||||||
setup_django(out_dir, check_db=False)
|
setup_django(out_dir, check_db=False)
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
assert settings.DATABASE_FILE == os.path.join(out_dir, SQL_INDEX_FILENAME)
|
DATABASE_FILE = os.path.join(out_dir, SQL_INDEX_FILENAME)
|
||||||
print(f' √ {settings.DATABASE_FILE}')
|
print(f' √ {DATABASE_FILE}')
|
||||||
print()
|
print()
|
||||||
for migration_line in apply_migrations(out_dir):
|
for migration_line in apply_migrations(out_dir):
|
||||||
print(f' {migration_line}')
|
print(f' {migration_line}')
|
||||||
|
|
||||||
|
|
||||||
assert os.path.exists(settings.DATABASE_FILE)
|
assert os.path.exists(DATABASE_FILE)
|
||||||
|
|
||||||
# from django.contrib.auth.models import User
|
# from django.contrib.auth.models import User
|
||||||
# if IS_TTY and not User.objects.filter(is_superuser=True).exists():
|
# if IS_TTY and not User.objects.filter(is_superuser=True).exists():
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-10" style="text-align: right">
|
<div class="col-sm-10" style="text-align: right">
|
||||||
<a href="/add/">Add Links</a> |
|
<a href="/add/">Add Links</a> |
|
||||||
<a href="/admin/core/page/">Admin</a> |
|
<a href="/admin/core/snapshot/">Admin</a> |
|
||||||
<a href="https://github.com/pirate/ArchiveBox/wiki">Docs</a>
|
<a href="https://github.com/pirate/ArchiveBox/wiki">Docs</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# This is the example default configiration file for ArchiveBox.
|
# This is the example default configiration file for ArchiveBox.
|
||||||
#
|
#
|
||||||
# Copy example config from here into your project's ArchiveBox.conf file,
|
# Copy lines from here into your project's ArchiveBox.conf file and uncomment,
|
||||||
# DO NOT EDIT THIS FILE DIRECTLY!
|
# DO NOT EDIT THIS FILE DIRECTLY!
|
||||||
#
|
#
|
||||||
# See the list of all the possible options. documentation, and examples here:
|
# See the list of all the possible options. documentation, and examples here:
|
||||||
|
@ -11,10 +11,17 @@
|
||||||
# ONLY_NEW = False
|
# ONLY_NEW = False
|
||||||
# TIMEOUT = 60
|
# TIMEOUT = 60
|
||||||
# MEDIA_TIMEOUT = 3600
|
# MEDIA_TIMEOUT = 3600
|
||||||
# ACTIVE_THEME = default
|
|
||||||
# FOOTER_INFO = Content is hosted for personal archiving purposes only. Contact server owner for any takedown requests.
|
|
||||||
# URL_BLACKLIST = (://(.*\.)?facebook\.com)|(://(.*\.)?ebay\.com)|(.*\.exe$)
|
# URL_BLACKLIST = (://(.*\.)?facebook\.com)|(://(.*\.)?ebay\.com)|(.*\.exe$)
|
||||||
|
|
||||||
|
[SERVER_CONFIG]
|
||||||
|
# SECRET_KEY = ---------------- not a valid secret key ! ----------------
|
||||||
|
# DEBUG = False
|
||||||
|
# PUBLIC_INDEX = True
|
||||||
|
# PUBLIC_SNAPSHOTS = True
|
||||||
|
# FOOTER_INFO = Content is hosted for personal archiving purposes only. Contact server owner for any takedown requests.
|
||||||
|
# ACTIVE_THEME = default
|
||||||
|
|
||||||
|
|
||||||
[ARCHIVE_METHOD_TOGGLES]
|
[ARCHIVE_METHOD_TOGGLES]
|
||||||
# SAVE_TITLE = True
|
# SAVE_TITLE = True
|
||||||
# SAVE_FAVICON = True
|
# SAVE_FAVICON = True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue