Add /json endpoint and fix pasting via curl to /paste

pull/12/head
Cesura 4 years ago
parent 45192964ea
commit 7e68faf27f

@ -6,7 +6,7 @@ from os import environ
from distutils.util import strtobool
from threading import Thread
pastey_version = "0.4"
pastey_version = "0.4.1"
loaded_config = {}
loaded_themes = []
@ -25,7 +25,6 @@ config.listen_address = environ["PASTEY_LISTEN_ADDRESS"] if "PASTEY_LISTEN_ADDRE
config.listen_port = environ["PASTEY_LISTEN_PORT"] if "PASTEY_LISTEN_PORT" in environ else config.listen_port
config.use_whitelist = bool(strtobool(environ["PASTEY_USE_WHITELIST"])) if "PASTEY_USE_WHITELIST" in environ else config.use_whitelist
config.restrict_pasting = bool(strtobool(environ["PASTEY_RESTRICT_PASTING"])) if "PASTEY_RESTRICT_PASTING" in environ else config.restrict_pasting
config.restrict_raw_pasting = bool(strtobool(environ["PASTEY_RESTRICT_RAW_PASTING"])) if "PASTEY_RESTRICT_RAW_PASTING" in environ else config.restrict_raw_pasting
config.guess_threshold = float(environ["PASTEY_GUESS_THRESHOLD"]) if "PASTEY_GUESS_THRESHOLD" in environ else config.guess_threshold
config.recent_pastes = int(environ["PASTEY_RECENT_PASTES"]) if "PASTEY_RECENT_PASTES" in environ else config.recent_pastes
config.whitelist_cidr = environ["PASTEY_WHITELIST_CIDR"].split(",") if "PASTEY_WHITELIST_CIDR" in environ else config.whitelist_cidr

@ -88,7 +88,14 @@ def is_expired(paste):
# Build a URL, accounting for config options
def build_url(request, path="/"):
protocol = request.url.split('//')[0] if not config.force_https_links else "https:"
domain = request.url.split('//')[1].split("/")[0] if config.override_domain == "" else config.override_domain
# Check for HTTPS headers
if 'X-Forwarded-Proto' in request.headers and request.headers['X-Forwarded-Proto'] == "https":
protocol = "https:"
elif 'X-Forwarded-Port' in request.headers and request.headers['X-Forwarded-Port'] == "443":
protocol = "https:"
else:
protocol = request.url.split('//')[0] if not config.force_https_links else "https:"
return protocol + "//" + domain + path

@ -21,9 +21,6 @@ blacklist_cidr = []
# Restrict pasting functionality to whitelisted IPs
restrict_pasting = False
# Restrict raw pasting to whitelisted IPs
restrict_raw_pasting = True
# Rate limit for pasting (ignored for whitelisted users)
rate_limit = "5/hour"
@ -54,6 +51,8 @@ show_cli_button = True
# Include https in the generated links instead of http
# This assumes you are behind something else doing the SSL
# termination, but want the users to see https links
#
# This is normally handled by the HTTP headers now
force_https_links = False
# This can be used to specify a different domain for generated links

@ -5,6 +5,7 @@ from flask import Flask, render_template, request, redirect, abort
from urllib.parse import quote
from datetime import datetime
from os import environ
import json
# Load themes
loaded_themes = common.get_themes()
@ -116,33 +117,49 @@ def paste():
if config.restrict_pasting and not common.verify_whitelist(source_ip):
abort(401)
# Content field is necessary
if 'content' not in request.form:
abort(400)
content = request.form['content']
# Check if content is empty
if request.form['content'].strip() == "":
if content.strip() == "":
if 'cli' in request.form:
abort(400)
else:
return redirect("/new")
else:
# Verify form options
title = request.form['title'] if request.form['title'].strip() != "" else "Untitled"
title = request.form['title'] if ('title' in request.form and request.form['title'].strip() != "") else "Untitled"
single = True if 'single' in request.form else False
encrypt = True if 'encrypt' in request.form else False
expiration = int(request.form['expiration']) if 'expiration' in request.form else -1
# Create paste
unique_id, key = functions.new_paste(title, content, source_ip, expires=int(request.form['expiration']), single=single, encrypt=encrypt)
unique_id, key = functions.new_paste(title, content, source_ip, expires=expiration, single=single, encrypt=encrypt)
if encrypt:
# Return link if cli form option was set
if 'cli' in request.form:
return common.build_url(request, "/view/" + unique_id + "/" + quote(key)), 200
else:
return redirect("/view/" + unique_id + "/" + quote(key))
else:
if 'cli' in request.form:
return common.build_url(request, "/view/" + unique_id), 200
else:
return redirect("/view/" + unique_id)
# POST new raw paste
@app.route('/raw', methods = ['POST'])
@limiter.limit(config.rate_limit, exempt_when=lambda: common.verify_whitelist(common.get_source_ip(request)))
def raw():
def paste_raw():
source_ip = common.get_source_ip(request)
# Check if restrict pasting to whitelist CIDRs is enabled
if config.restrict_raw_pasting and not common.verify_whitelist(source_ip):
if config.restrict_pasting and not common.verify_whitelist(source_ip):
abort(401)
# Create paste
@ -151,6 +168,44 @@ def raw():
return link, 200
# POST new json paste
@app.route('/json', methods = ['POST'])
@limiter.limit(config.rate_limit, exempt_when=lambda: common.verify_whitelist(common.get_source_ip(request)))
def paste_json():
source_ip = common.get_source_ip(request)
# Check if restrict pasting to whitelist CIDRs is enabled
if config.restrict_pasting and not common.verify_whitelist(source_ip):
abort(401)
# Check json integrity
try:
paste = json.loads(request.data)
except json.JSONDecodeError:
abort(400)
# Content field is mandatory
if 'content' not in paste or paste['content'].strip() == "":
abort(400)
content = paste['content']
# Optional fields
title = paste['title'] if ('title' in paste and paste['title'].strip() != "") else "Untitled"
single = paste['single'] if ('single' in paste and type(paste['single']) == bool) else False
encrypt = paste['encrypt'] if ('encrypt' in paste and type(paste['encrypt']) == bool) else False
expiration = paste['expiration'] if ('expiration' in paste and type(paste['expiration']) == int) else -1
# Create paste
unique_id, key = functions.new_paste(title, content, source_ip, expires=expiration, single=single, encrypt=encrypt)
if encrypt:
return {
"link": common.build_url(request, "/view/" + unique_id + "/" + quote(key))
}, 200
else:
return {
"link": common.build_url(request, "/view/" + unique_id)
}, 200
# Custom 404 handler
@app.errorhandler(404)
def page_not_found(e):

@ -129,15 +129,40 @@
<div class="row justify-content-md-center">
<div class="col-md-4">
<input class="form-control pastey-input" id="paste-url" type="text" value="{{ script_url }}" readonly />
<input class="form-control pastey-input pastey-view-url" id="paste-url" type="text" value="{{ script_url }}" readonly />
</div>
<div class="col-md-1">
<a href="{{ script_url }}">
<button type="button" class="btn btn-success text-nowrap"><i class="fas fa-download"></i>&nbsp;&nbsp;&nbsp;Download</button>
</a>
</div>
</div><br />
<div class="row text-center">
<div class="col-md-12">
<h1 class="mb-3 h4">JSON</h1>
<p>You can also send a properly-formatted json POST request to <span style="font-weight:bold;">/json</span>:</p>
</div>
</div>
<div class="row justify-content-md-center">
<div class="col-md-3">
<pre>{
"content": "This is a paste",
"title": "Interesting title",
"expiration": -1,
"encrypt": true,
"single": false
}</pre>
</div>
</div>
<div class="row text-center">
<div class="col-md-12">
<p>Note that <span style="font-weight:bold;">expiration</span> is some value in hours, and that -1 = no expiration date.
Only the <span style="font-weight:bold;">content</span> field is mandatory.</p>
</div>
</div>
</div>
</main>
<!--Main layout-->

Loading…
Cancel
Save