1
0
Fork 0
mirror of synced 2024-06-02 10:34:43 +12:00

expose more django server config options

This commit is contained in:
Nick Sweeting 2019-05-02 19:15:16 -04:00
parent d016f1efb5
commit 3c3b2ee621
8 changed files with 89 additions and 37 deletions

View file

@ -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:

View file

@ -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

View file

@ -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

View file

@ -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'),
] ]

View file

@ -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):

View file

@ -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():

View file

@ -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> &nbsp; | &nbsp; <a href="/add/">Add Links</a> &nbsp; | &nbsp;
<a href="/admin/core/page/">Admin</a> &nbsp; | &nbsp; <a href="/admin/core/snapshot/">Admin</a> &nbsp; | &nbsp;
<a href="https://github.com/pirate/ArchiveBox/wiki">Docs</a> <a href="https://github.com/pirate/ArchiveBox/wiki">Docs</a>
</div> </div>
</div> </div>

View file

@ -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