Put config app dir

This commit is contained in:
ksamuel 2020-08-13 14:36:42 +02:00
parent 2d3f3998de
commit 6c1dad2626
9 changed files with 112 additions and 111 deletions

View File

@ -1,6 +0,0 @@
#!/usr/bin/env python
# coding: utf-8
from zerobin.cmd import main
main()

5
zerobin/__main__.py Normal file
View File

@ -0,0 +1,5 @@
#!/usr/bin/env python
from zerobin.cli import main
main()

View File

@ -7,16 +7,20 @@
import sys
import re
import os
import zerobin
from zerobin.utils import (
settings,
SettingsValidationError,
ensure_var_env,
ensure_app_context,
hash_password,
)
from zerobin.routes import get_app
from zerobin.paste import Paste
from bottle import run
import clize
@ -26,11 +30,9 @@ def runserver(
*,
host="",
port="",
config_dir="",
data_dir="",
debug=None,
user="",
group="",
settings_file="",
compressed_static=None,
version=False,
paste_id_length=None,
server="paste",
@ -39,23 +41,18 @@ def runserver(
print("0bin V%s" % settings.VERSION)
sys.exit(0)
settings.HOST = host or settings.HOST
settings.PORT = port or settings.PORT
settings.USER = user or settings.USER
settings.GROUP = group or settings.GROUP
settings.PASTE_ID_LENGTH = paste_id_length or settings.PASTE_ID_LENGTH
settings.DEBUG = bool(debug) if debug is not None else settings.DEBUG
ensure_var_env()
try:
_, app = get_app(debug, settings_file, compressed_static, settings=settings)
settings, app = get_app(debug=debug, config_dir=config_dir, data_dir=data_dir,)
except SettingsValidationError as err:
print("Configuration error: %s" % err.message, file=sys.stderr)
sys.exit(1)
settings.HOST = host or os.environ.get("ZEROBIN_HOST", settings.HOST)
settings.PORT = port or os.environ.get("ZEROBIN_PORT", settings.PORT)
if settings.DEBUG:
print(f"Admin URL: http://{settings.HOST}:{settings.PORT}{settings.ADMIN_URL}")
print(f"Admin URL: {settings.ADMIN_URL}")
print()
run(
app, host=settings.HOST, port=settings.PORT, reloader=True, server=server,
)
@ -100,7 +97,7 @@ def delete_paste(*pastes, quiet=False):
print("Paste {} doesn't exist".format(paste_uuid))
def print_admin_url():
def infos():
""" Print the route to the 0bin admin.
The admin route is generated by zerobin so that bots won't easily
@ -123,8 +120,16 @@ def print_admin_url():
"""
ensure_var_env()
print(settings.ADMIN_URL)
ensure_app_context()
print(f"Zerobin version: {zerobin.__version__}")
print(f"Admin URL (to moderate pastes): {settings.ADMIN_URL}")
print(f"Data dir (pastes and counter): {settings.DATA_DIR}")
print(
f"Config dir (config file, secret key, admin password and custom views): {settings.CONFIG_DIR}"
)
print(
f"Static files dir (to configure apache, nging, etc.): {settings.STATIC_FILES_ROOT}"
)
def set_admin_password(password):
@ -134,17 +139,17 @@ def set_admin_password(password):
"""
ensure_var_env()
ensure_app_context()
settings.ADMIN_PASSWORD_FILE.write_bytes(hash_password(password))
def main():
subcommands = [runserver, delete_paste, print_admin_url, set_admin_password]
subcommands = [runserver, delete_paste, infos, set_admin_password]
subcommand_names = [
clize.util.name_py2cli(name)
for name in clize.util.dict_from_names(subcommands).keys()
]
if len(sys.argv) < 2 or sys.argv[1] not in subcommand_names:
sys.argv.insert(1, subcommand_names[0])
clize.run(runserver, delete_paste, print_admin_url, set_admin_password)
clize.run(runserver, delete_paste, infos, set_admin_password)

View File

@ -1,57 +1,19 @@
from zerobin import ROOT_DIR
# Path to the directory that will contains all variable content, such
# as pastes, the secret key, etc
VAR_DIR = ROOT_DIR.parent / "var"
# debug will get you error messages and auto reload
# don't set this to True in production
# Get error messages and auto reload.
# Don't set this to True in production
DEBUG = False
# Should the application serve static files on it's own ?
# If yes, set the absolute path to the static files.
# If no, set it to None
# In dev this is handy, in prod you probably want the HTTP servers
# to serve it, but it's OK for small traffic to set it to True in prod too.
STATIC_FILES_ROOT = ROOT_DIR / "static"
# If True, will link the compressed verion of the js and css files,
# otherwise, will use the ordinary files
COMPRESSED_STATIC_FILES = False
# A tuple of absolute paths of directory where to look the template for
# the first one will be the first to be looked into
# if you want to override, it needs to be it a directory at the begining of
# this tuple. By default, custom_views is meant for that purpose.
TEMPLATE_DIRS = (
VAR_DIR / "custom_views",
ROOT_DIR / "views",
)
# Port and host the embeded python server should be using
# You can also specify them using the --host and --port script options
# which have priority on these settings
# Port and host the embedded python server should be using
HOST = "127.0.0.1"
PORT = "8000"
# User and group the server should run as. Set to None if it should be the
# current user. Some OS don't support it and if so, it will be ignored.
USER = None
GROUP = None
PORT = "3255"
# Display a tiny counter for pastes created.
# Be carreful if your site have to many pastes this can hurt your hard drive performances.
# Refresh counter interval. Default to every minute after a paste.
DISPLAY_COUNTER = True
REFRESH_COUNTER = 60 * 1 # Fill this if you want to
ADMIN_CREDENTIALS = {
"username": None,
"password": None,
}
# Refresh counter interval.
REFRESH_COUNTER = 60 # in seconds
# Names/links to insert in the menu bar.
# Any link with "mailto:" will be escaped to prevent spam
# Names/links to insert in the footer.
# Any link with "mailto:" will be escaped to limit spam, but displayed
# correctly to the user using JS.
MENU = (
("Create paste", "/"), # internal link. First link will be highlited
("Github", "https://github.com/Tygs/0bin"), # external link
@ -60,11 +22,11 @@ MENU = (
("Zerobin Pastebin", "https://www.0bin.net/"), # Thanks the authors :)
)
# limit size of pasted text in bytes. Be careful allowing too much size can
# slow down user's browser
# Size limit of the paste content in bytes. Be careful, allowing a size too big can
# slow down the user's browser
MAX_SIZE = 1024 * 500
# length of base64-like paste-id string in the url, int from 4 to 27 (length of sha1 digest)
# Length of the paste-id string in the url, int from 4 to 27 (length of sha1 digest)
# total number of unique pastes can be calculated as 2^(6*PASTE_ID_LENGTH)
# for PASTE_ID_LENGTH=8, for example, it's 2^(6*8) = 281 474 976 710 656
PASTE_ID_LENGTH = 8

View File

@ -27,15 +27,15 @@ from beaker.middleware import SessionMiddleware
from zerobin import __version__
from zerobin.utils import (
settings,
SettingsValidationError,
ensure_var_env,
ensure_app_context,
check_password,
settings,
)
from zerobin.paste import Paste
ensure_var_env()
ensure_app_context()
GLOBAL_CONTEXT = {
@ -235,33 +235,33 @@ def server_static(filename):
return static_file(filename, root=settings.STATIC_FILES_ROOT)
def get_app(debug=None, settings_file="", compressed_static=None, settings=settings):
def get_app(debug=None, config_dir="", data_dir=""):
"""
Return a tuple (settings, app) configured using passed
parameters and/or a setting file.
"""
settings_file = settings_file or os.environ.get("ZEROBIN_SETTINGS_FILE")
data_dir = data_dir or os.environ.get("ZEROBIN_DATA_DIR")
config_dir = config_dir or os.environ.get("ZEROBIN_CONFIG_DIR")
if settings_file:
settings.update_with_file(os.path.realpath(settings_file))
ensure_app_context(config_dir=config_dir, data_dir=data_dir)
settings.DEBUG = bool(debug or os.environ.get("ZEROBIN_DEBUG", settings.DEBUG))
settings.DISPLAY_COUNTER = bool(
os.environ.get("ZEROBIN_DISPLAY_COUNTER", settings.DISPLAY_COUNTER)
)
settings.REFRESH_COUNTER = int(
os.environ.get("ZEROBIN_REFRESH_COUNTER", settings.REFRESH_COUNTER)
)
settings.MAX_SIZE = int(os.environ.get("ZEROBIN_MAX_SIZE", settings.MAX_SIZE))
settings.PASTE_ID_LENGTH = int(
os.environ.get("ZEROBIN_PASTE_ID_LENGTH", settings.PASTE_ID_LENGTH)
)
if settings.PASTE_ID_LENGTH < 4:
raise SettingsValidationError("PASTE_ID_LENGTH cannot be lower than 4")
if compressed_static is not None:
settings.COMPRESSED_STATIC_FILES = compressed_static
if debug is not None:
settings.DEBUG = debug
# make sure the templates can be loaded
for d in reversed(settings.TEMPLATE_DIRS):
bottle.TEMPLATE_PATH.insert(0, d)
if settings.DEBUG:
bottle.debug(True)
return settings, app

View File

@ -18,8 +18,6 @@ setTimeout(function () {
document.getElementById('content').focus()
}, 100)
const app = new Vue({
el: '#app',

View File

@ -8,6 +8,13 @@ import hashlib
import secrets
from functools import partial
from pathlib import Path
import bottle
from appdirs import AppDirs
import zerobin
from zerobin import default_settings
@ -92,7 +99,7 @@ def as_unicode(obj):
return str(obj)
def ensure_var_env():
def ensure_app_context(data_dir=None, config_dir=None):
""" Ensure all the variable things we generate are available.
This will make sure we have:
@ -101,20 +108,39 @@ def ensure_var_env():
- a content dir
- a secret key
- an admin URL
This function is idempotent if nothing touch the files it created.
"""
settings.VAR_DIR.mkdir(exist_ok=True, parents=True)
settings.PASTE_FILES_ROOT = settings.VAR_DIR / "content"
app_dirs = AppDirs("0bin", "tygs")
settings.DATA_DIR = Path(data_dir or app_dirs.user_data_dir).expanduser()
settings.DATA_DIR.mkdir(exist_ok=True, parents=True)
settings.CONFIG_DIR = Path(config_dir or app_dirs.user_config_dir).expanduser()
settings.CONFIG_DIR.mkdir(exist_ok=True, parents=True)
settings.STATIC_FILES_ROOT = zerobin.ROOT_DIR / "static"
settings.PASTE_FILES_ROOT = settings.DATA_DIR / "pastes"
settings.PASTE_FILES_ROOT.mkdir(exist_ok=True)
settings.SESSIONS_DIR = settings.VAR_DIR / "sessions"
settings.SESSIONS_DIR = settings.DATA_DIR / "sessions"
settings.SESSIONS_DIR.mkdir(exist_ok=True)
secret_key_file = settings.VAR_DIR / "secret_key"
bottle.TEMPLATE_PATH.insert(0, zerobin.ROOT_DIR / "views")
CUSTOM_VIEWS_DIR = settings.CONFIG_DIR / "custom_views"
CUSTOM_VIEWS_DIR.mkdir(exist_ok=True)
bottle.TEMPLATE_PATH.insert(0, CUSTOM_VIEWS_DIR)
secret_key_file = settings.CONFIG_DIR / "secret_key"
if not secret_key_file.is_file():
secret_key_file.write_text(secrets.token_urlsafe(64))
settings.SECRET_KEY = secret_key_file.read_text()
admin_password_file = settings.VAR_DIR / "admin_password"
admin_password_file = settings.CONFIG_DIR / "admin_password"
if not secret_key_file.is_file():
admin_password_file.write_text(
"No password set. Use the set_admin_passord command. Don't write this file by hand."
@ -124,6 +150,13 @@ def ensure_var_env():
payload = ("admin" + settings.SECRET_KEY).encode("ascii")
settings.ADMIN_URL = "/admin/" + hashlib.sha256(payload).hexdigest() + "/"
settings_file = settings.CONFIG_DIR / "settings.py"
if not settings_file.is_file():
default_config = (zerobin.ROOT_DIR / "default_settings.py").read_text()
settings_file.write_text(default_config)
settings.update_with_file(settings_file)
def hash_password(password):
return hashlib.scrypt(

View File

@ -12,7 +12,7 @@
<link rel="icon" href="/static/img/favicon.ico" />
%if settings.COMPRESSED_STATIC_FILES:
%if not settings.DEBUG:
<link href="/static/css/style.min.css?{{ VERSION }}" rel="stylesheet" />
%else:
<link href="/static/css/prettify.css" rel="stylesheet" />
@ -94,10 +94,11 @@
</div>
<script src="/static/js/vue.js"></script>
%if settings.COMPRESSED_STATIC_FILES:
%if not settings.DEBUG:
<script src="/static/js/main.min.js?{{ VERSION }}"></script>
%else:
<script src="/static/js/vue.js"></script>
<script src="/static/js/sjcl.js"></script>
<script src="/static/js/behavior.js?{{ VERSION }}"></script>
%end
@ -107,8 +108,8 @@
</script>
%if settings.COMPRESSED_STATIC_FILES:
<script src="/static/js/additional.min.js?{{ settings.VERSION }}"></script>
%if not settings.DEBUG:
<script src="/static/js/additional.min.js?{{ VERSION }}"></script>
%else:
<script src="/static/js/lzw.js"></script>
<script src="/static/js/prettify.min.js"></script>

3
zerobin/wsgi.py Normal file
View File

@ -0,0 +1,3 @@
from zerobin.wsgi import setup_app
settings, app = get_app()