mirror of
https://github.com/Tygs/0bin.git
synced 2023-08-10 21:13:00 +03:00
Put config app dir
This commit is contained in:
parent
2d3f3998de
commit
6c1dad2626
@ -1,6 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# coding: utf-8
|
||||
|
||||
from zerobin.cmd import main
|
||||
|
||||
main()
|
5
zerobin/__main__.py
Normal file
5
zerobin/__main__.py
Normal file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from zerobin.cli import main
|
||||
|
||||
main()
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -18,8 +18,6 @@ setTimeout(function () {
|
||||
document.getElementById('content').focus()
|
||||
}, 100)
|
||||
|
||||
|
||||
|
||||
const app = new Vue({
|
||||
|
||||
el: '#app',
|
||||
|
@ -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(
|
||||
|
@ -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
3
zerobin/wsgi.py
Normal file
@ -0,0 +1,3 @@
|
||||
from zerobin.wsgi import setup_app
|
||||
|
||||
settings, app = get_app()
|
Loading…
Reference in New Issue
Block a user