Merged in feature/HTTPASTE-16/controller/ui (pull request #45)
Feature/HTTPASTE-16/controller/ui
This commit is contained in:
commit
c645478b98
24 changed files with 698 additions and 9 deletions
|
|
@ -40,4 +40,5 @@ where = src
|
||||||
[options.package_data]
|
[options.package_data]
|
||||||
* =
|
* =
|
||||||
*.json
|
*.json
|
||||||
*.sql
|
*.sql
|
||||||
|
*.html
|
||||||
|
|
@ -15,4 +15,4 @@ def get(**kwargs):
|
||||||
paste_lifetime=model.paste.default_lifetime,
|
paste_lifetime=model.paste.default_lifetime,
|
||||||
paste_max_lifetime=str(round(model.paste.default_max_lifetime / 60)),
|
paste_max_lifetime=str(round(model.paste.default_max_lifetime / 60)),
|
||||||
paste_default_encoding=model.paste.default_encoding
|
paste_default_encoding=model.paste.default_encoding
|
||||||
), 200
|
), 302, {'Location': '/ui'}
|
||||||
|
|
|
||||||
13
src/httpaste/controller/ui/__init__.py
Normal file
13
src/httpaste/controller/ui/__init__.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste import __doc__ as man_page
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/search.html")
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
'paste_index_url': '/ui/paste',
|
||||||
|
'man_page': man_page
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.render(**variables), 200
|
||||||
90
src/httpaste/controller/ui/paste/__init__.py
Normal file
90
src/httpaste/controller/ui/paste/__init__.py
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
from io import BytesIO
|
||||||
|
from base64 import b64encode
|
||||||
|
|
||||||
|
from connexion import request
|
||||||
|
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste.helper.url import url_query_string, url_append_query_param
|
||||||
|
from httpaste.controller.paste import post as post_raw
|
||||||
|
from httpaste.controller.paste import get as get_raw
|
||||||
|
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/paste/search.html")
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
'create_public_paste_url': '/ui/paste/public',
|
||||||
|
'create_private_paste_url': '/ui/paste/private',
|
||||||
|
'user': kwargs.get('user'),
|
||||||
|
'delete_session_url': '/ui/user/session/delete'
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.render(**variables), 200
|
||||||
|
|
||||||
|
|
||||||
|
def post(**kwargs):
|
||||||
|
|
||||||
|
#rewriting strict form to mixed (as expected by cascaded controller)
|
||||||
|
data = kwargs['body'].pop('data')
|
||||||
|
kwargs = {**kwargs, **kwargs['body']}
|
||||||
|
kwargs.pop('body')
|
||||||
|
kwargs['body'] = {'data': data}
|
||||||
|
|
||||||
|
#prepare octet stream data for cascaded controller
|
||||||
|
if kwargs.get('data').filename:
|
||||||
|
bfr = BytesIO()
|
||||||
|
kwargs.get('data').save(bfr)
|
||||||
|
bfr.seek(0)
|
||||||
|
kwargs['body']['data'] = b64encode(bfr.read()).decode('utf-8')
|
||||||
|
kwargs['encoding'] = 'base64'
|
||||||
|
|
||||||
|
output, status_code = post_raw(**kwargs)
|
||||||
|
|
||||||
|
#TODO: lifetime=-1 no preview handler
|
||||||
|
|
||||||
|
url = output.strip('\n')
|
||||||
|
if kwargs.get('lifetime') and int(kwargs['lifetime']) < 0:
|
||||||
|
url = url_append_query_param(url, 'preview', 'False')
|
||||||
|
|
||||||
|
return output, 302, {'Location': url}
|
||||||
|
|
||||||
|
|
||||||
|
def get(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/paste/get.html")
|
||||||
|
|
||||||
|
base_path = f'paste/public/{kwargs["id"]}'
|
||||||
|
|
||||||
|
raw_paste_url = f'{request.host_url}{base_path}'
|
||||||
|
if kwargs.get('user'):
|
||||||
|
raw_paste_url = f'{request.host_url}{base_path}'
|
||||||
|
|
||||||
|
paste_url = raw_paste_url
|
||||||
|
|
||||||
|
paste_url_query = {}
|
||||||
|
for field in ['format', 'mime', 'syntax']:
|
||||||
|
if kwargs.get(field):
|
||||||
|
paste_url_query[field] = kwargs[field]
|
||||||
|
|
||||||
|
if paste_url_query:
|
||||||
|
paste_url = '?'.join((paste_url, url_query_string(paste_url_query)))
|
||||||
|
|
||||||
|
preview_url = f'/ui/{base_path}'
|
||||||
|
if kwargs.get('preview'):
|
||||||
|
paste_url_query['preview'] = kwargs['preview']
|
||||||
|
preview_url = '?'.join((preview_url, url_query_string(paste_url_query)))
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
'raw_paste_url': raw_paste_url,
|
||||||
|
'paste_url': paste_url,
|
||||||
|
'preview_url': preview_url,
|
||||||
|
'query': {
|
||||||
|
'format': kwargs.get('format', ''),
|
||||||
|
'syntax': kwargs.get('syntax', ''),
|
||||||
|
'mime': kwargs.get('mime', ''),
|
||||||
|
'preview': kwargs.get('preview', True)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.render(**variables)
|
||||||
24
src/httpaste/controller/ui/paste/private.py
Normal file
24
src/httpaste/controller/ui/paste/private.py
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste.controller.ui.paste import post as post_proxy
|
||||||
|
from httpaste.controller.ui.paste import get as get_proxy
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/paste/private/search.html")
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
'paste_form_url': '/ui/paste/private',
|
||||||
|
'user': kwargs.get('user')
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.render(**variables), 200
|
||||||
|
|
||||||
|
|
||||||
|
def post(**kwargs):
|
||||||
|
|
||||||
|
return post_proxy(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def get(**kwargs):
|
||||||
|
|
||||||
|
return get_proxy(**kwargs)
|
||||||
23
src/httpaste/controller/ui/paste/public.py
Normal file
23
src/httpaste/controller/ui/paste/public.py
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste.controller.ui.paste import post as post_proxy
|
||||||
|
from httpaste.controller.ui.paste import get as get_proxy
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/paste/public/search.html")
|
||||||
|
|
||||||
|
variables = {
|
||||||
|
'paste_form_url': '/ui/paste/public'
|
||||||
|
}
|
||||||
|
|
||||||
|
return template.render(**variables), 200
|
||||||
|
|
||||||
|
|
||||||
|
def post(**kwargs):
|
||||||
|
|
||||||
|
return post_proxy(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def get(**kwargs):
|
||||||
|
|
||||||
|
return get_proxy(**kwargs)
|
||||||
0
src/httpaste/controller/ui/user/__init__.py
Normal file
0
src/httpaste/controller/ui/user/__init__.py
Normal file
19
src/httpaste/controller/ui/user/session/__init__.py
Normal file
19
src/httpaste/controller/ui/user/session/__init__.py
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste.controller.user.session import delete as raw_delete
|
||||||
|
|
||||||
|
from connexion import request
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
template = views.get_template("viewport/ui/user/session/search.html")
|
||||||
|
|
||||||
|
print(request.path)
|
||||||
|
|
||||||
|
variables = {'session_delete_url': request.path + '/delete'}
|
||||||
|
|
||||||
|
return template.render(**variables), 200
|
||||||
|
|
||||||
|
|
||||||
|
def delete(**kwargs):
|
||||||
|
|
||||||
|
return raw_delete(**kwargs)
|
||||||
6
src/httpaste/controller/ui/user/session/delete.py
Normal file
6
src/httpaste/controller/ui/user/session/delete.py
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
from httpaste.helper.template import views
|
||||||
|
from httpaste.controller.ui.user.session import delete as proxy_delete
|
||||||
|
|
||||||
|
def search(**kwargs):
|
||||||
|
|
||||||
|
return proxy_delete(**kwargs)
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"""
|
"""
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
|
||||||
from httpaste.helper.http import ForbiddenError
|
from httpaste.helper.http import UnauthorizedError
|
||||||
from httpaste.model.user import authenticate, AuthenticationError
|
from httpaste.model.user import authenticate, AuthenticationError
|
||||||
from httpaste.backend import load_backend
|
from httpaste.backend import load_backend
|
||||||
|
|
||||||
|
|
@ -22,4 +22,11 @@ def post(*args, **kwargs):
|
||||||
return authenticate(user_id, password, backend.user, context)
|
return authenticate(user_id, password, backend.user, context)
|
||||||
except AuthenticationError as e:
|
except AuthenticationError as e:
|
||||||
|
|
||||||
raise ForbiddenError('You shall not pass!') from e
|
raise UnauthorizedError('You shall not pass!') from e
|
||||||
|
|
||||||
|
|
||||||
|
def delete(**kwargs):
|
||||||
|
"""
|
||||||
|
"""
|
||||||
|
|
||||||
|
raise UnauthorizedError('Authentication Rejection requested by client')
|
||||||
|
|
@ -21,7 +21,7 @@ class UnauthorizedError(RuntimeError):
|
||||||
return {
|
return {
|
||||||
"detail": str(error),
|
"detail": str(error),
|
||||||
"status": 401,
|
"status": 401,
|
||||||
"title": "Unauthorized s",
|
"title": "Unauthorized",
|
||||||
}, 401
|
}, 401
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
6
src/httpaste/helper/template.py
Normal file
6
src/httpaste/helper/template.py
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||||
|
|
||||||
|
views = Environment(
|
||||||
|
loader=PackageLoader("httpaste", "views"),
|
||||||
|
autoescape=select_autoescape()
|
||||||
|
)
|
||||||
20
src/httpaste/helper/url.py
Normal file
20
src/httpaste/helper/url.py
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
|
||||||
|
|
||||||
|
def url_query_string(fields:dict):
|
||||||
|
|
||||||
|
return '&'.join([f'{k}={v}' for k,v in fields.items()])
|
||||||
|
|
||||||
|
|
||||||
|
def url_append_query_param(url:str, name: str, value:str):
|
||||||
|
|
||||||
|
urlcomps = urlparse(url)
|
||||||
|
|
||||||
|
q = parse_qs(urlcomps.query)
|
||||||
|
|
||||||
|
q[name] = value
|
||||||
|
|
||||||
|
qs = url_query_string(q)
|
||||||
|
|
||||||
|
return urlcomps._replace(query=qs).geturl()
|
||||||
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
"get": {
|
"get": {
|
||||||
"description": "get description",
|
"description": "get description",
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"303": {
|
||||||
"description": "",
|
"description": "",
|
||||||
"content": {
|
"content": {
|
||||||
"text/plain": {
|
"text/plain": {
|
||||||
|
|
@ -185,6 +185,258 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"/ui": {
|
||||||
|
"get": {
|
||||||
|
"description": "create a new public paste",
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/paste": {
|
||||||
|
"get": {
|
||||||
|
"description": "create a new public paste",
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/paste/public": {
|
||||||
|
"get": {
|
||||||
|
"description": "create a new public paste UI-driven",
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"description": "create a new public paste",
|
||||||
|
"requestBody": {
|
||||||
|
"$ref": "#/components/requestBodies/pastePost"
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/lifetime"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PasteURL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/paste/private": {
|
||||||
|
"get": {
|
||||||
|
"description": "create a new public paste UI-driven",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"basicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"description": "create a new public paste",
|
||||||
|
"requestBody": {
|
||||||
|
"$ref": "#/components/requestBodies/pastePost"
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"basicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/lifetime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/encoding"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste location",
|
||||||
|
"content": {
|
||||||
|
"text/plain": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PasteURL"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/paste/public/{id}": {
|
||||||
|
"get": {
|
||||||
|
"description": "get a public paste",
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/syntax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/format"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/linenos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/mime"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/ui_preview"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste data. content type may vary.",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PasteData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/paste/private/{id}": {
|
||||||
|
"get": {
|
||||||
|
"description": "get a public paste",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"basicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/id"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/syntax"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/format"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/linenos"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"$ref": "#/components/parameters/mime"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste data. content type may vary.",
|
||||||
|
"content": {
|
||||||
|
"text/html": {
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/PasteData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/user/session": {
|
||||||
|
"get": {
|
||||||
|
"description": "get a public paste",
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"basicAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste data. content type may vary.",
|
||||||
|
"content": {
|
||||||
|
"text/html": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/ui/user/session/delete": {
|
||||||
|
"get": {
|
||||||
|
"description": "get a public paste",
|
||||||
|
"security": [
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "paste data. content type may vary.",
|
||||||
|
"content": {
|
||||||
|
"text/html": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"components": {
|
"components": {
|
||||||
|
|
@ -215,9 +467,9 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "binary"
|
"format": "binary"
|
||||||
},
|
},
|
||||||
"rsa_public_key": {
|
"fileName": {
|
||||||
"description": "RSA public key",
|
"type": "string",
|
||||||
"type": "string"
|
"format": "binary"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": [
|
"required": [
|
||||||
|
|
@ -294,6 +546,15 @@
|
||||||
"schema": {
|
"schema": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ui_preview": {
|
||||||
|
"description": "enable preview in UI",
|
||||||
|
"name": "preview",
|
||||||
|
"in": "query",
|
||||||
|
"required": false,
|
||||||
|
"schema": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"securitySchemes": {
|
"securitySchemes": {
|
||||||
|
|
|
||||||
26
src/httpaste/views/container/get_paste_form.html
Normal file
26
src/httpaste/views/container/get_paste_form.html
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
<form class="color-theme font-theme" action="{{preview_url}}" method="get" enctype="multipart/form-data">
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<label for="syntax">Syntax</label>
|
||||||
|
<input type="text" name="syntax" value="{{ query['syntax'] }}"/>
|
||||||
|
|
||||||
|
</summary>
|
||||||
|
<a href="https://pygments.org/docs/lexers/" target="_blank">Pygments lexer short name</a> <i>(e.g. 'terraform', 'python')</i>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<label for="format">Format</label>
|
||||||
|
<input type="text" name="format" value="{{ query['format'] }}"/>
|
||||||
|
</summary>
|
||||||
|
<a href="https://pygments.org/docs/formatters/" target="_blank">Pygments formatter short name</a> <i>(e.g. 'html', 'terminal256')</i>
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<label for="mime">Content-Type (MIME)</label>
|
||||||
|
<input type="text" name="mime" value="{{ query['mime'] }}"/>
|
||||||
|
</summary>
|
||||||
|
Content-Type Header the server should return
|
||||||
|
</details>
|
||||||
|
<input type="text" name="preview" value="{{ query['preview'] }}" class="hidden"/>
|
||||||
|
<input type="submit" value="☝ Refresh"/>
|
||||||
|
</form>
|
||||||
21
src/httpaste/views/container/post_paste_form.html
Normal file
21
src/httpaste/views/container/post_paste_form.html
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
<form class="color-theme font-theme" action="{{paste_form_url}}" method="post" enctype="multipart/form-data" target="_top">
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<label for="data">Data</label>
|
||||||
|
<div><textarea name="data" cols="60" rows="10" style="width:100%"></textarea><br/>
|
||||||
|
<input type="file" id="myfile" name="data"/>
|
||||||
|
</div>
|
||||||
|
</summary>
|
||||||
|
Either supply a past text, or upload a file.
|
||||||
|
</details>
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
<label for="lifetime">Lifetime</label>
|
||||||
|
<input type="number" id="lname" name="lifetime" value="5">
|
||||||
|
</summary>
|
||||||
|
Set a paste’s lifetime to make it expire after a specified amount of time.<br/>
|
||||||
|
The lifetime must be provided in minutes and cannot be less than 1<br/>(, unless lesser than 0).<br/>
|
||||||
|
A lifetime of 0 will evaluate to a lifetime 1.
|
||||||
|
</details>
|
||||||
|
<input type="submit" value="☝ Paste"/>
|
||||||
|
</form>
|
||||||
58
src/httpaste/views/frame/base.html
Normal file
58
src/httpaste/views/frame/base.html
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-theme details {
|
||||||
|
background-color: #EEE;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-theme details {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-theme details > summary {
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font-theme details > summary {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
details {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
details > summary {
|
||||||
|
list-style-type: '?';
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
31
src/httpaste/views/frame/decorated.html
Normal file
31
src/httpaste/views/frame/decorated.html
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iframe {
|
||||||
|
width: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
27
src/httpaste/views/viewport/ui/paste/get.html
Normal file
27
src/httpaste/views/viewport/ui/paste/get.html
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{% extends 'frame/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<a href="/">Return</a>
|
||||||
|
<h1>Paste Conditioner</h1>
|
||||||
|
{% if query['preview'] %}
|
||||||
|
Preview
|
||||||
|
<iframe src="{{paste_url}}" title="as" style="resize:both; width: 100%"></iframe>
|
||||||
|
<hr/>
|
||||||
|
{% else %}
|
||||||
|
<p><b>Preview is disabled.</b>
|
||||||
|
<br/>
|
||||||
|
This probably happened because the paste is set to expire after read.
|
||||||
|
<br/>
|
||||||
|
<i>You can still proceed to condition the paste URL.</i>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
{% include 'container/get_paste_form.html' %}
|
||||||
|
<div style="justify-content: center">
|
||||||
|
<hr/>
|
||||||
|
<h3>Paste URLs</h3>
|
||||||
|
Formatted: <a href="{{paste_url}}" target="_top">{{paste_url}}</a>
|
||||||
|
<br/>
|
||||||
|
Raw: <a href="{{raw_paste_url}}" target="_top">{{raw_paste_url}}</a>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
5
src/httpaste/views/viewport/ui/paste/private/search.html
Normal file
5
src/httpaste/views/viewport/ui/paste/private/search.html
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends 'frame/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% include 'container/post_paste_form.html' %}
|
||||||
|
{% endblock %}
|
||||||
5
src/httpaste/views/viewport/ui/paste/public/search.html
Normal file
5
src/httpaste/views/viewport/ui/paste/public/search.html
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{% extends 'frame/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% include 'container/post_paste_form.html' %}
|
||||||
|
{% endblock %}
|
||||||
29
src/httpaste/views/viewport/ui/paste/search.html
Normal file
29
src/httpaste/views/viewport/ui/paste/search.html
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<title></title>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
<a href="{{create_private_paste_url}}">Create a Private Paste</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{create_public_paste_url}}">Create a Public Paste</a>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a href="{{ delete_session_url }}" target="_blank" style="text-align: center">
|
||||||
|
Flush Local HTTP Authentication Cache
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
11
src/httpaste/views/viewport/ui/search.html
Normal file
11
src/httpaste/views/viewport/ui/search.html
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{% extends 'frame/decorated.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<header style="display: flex; justify-content: center">
|
||||||
|
<details>
|
||||||
|
<summary style="text-align: center"><a href="/">httpaste - versatile HTTP pastebin (User Interface)</a></summary>
|
||||||
|
<textarea readonly="true" style="width: 100%">{{ man_page }}</textarea>
|
||||||
|
</details>
|
||||||
|
</header>
|
||||||
|
<iframe src="{{ paste_index_url }}" title="" class="iframe"></iframe>
|
||||||
|
{% endblock %}
|
||||||
6
src/httpaste/views/viewport/ui/user/session/search.html
Normal file
6
src/httpaste/views/viewport/ui/user/session/search.html
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends 'frame/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<a href="{{ session_delete_url }}">Clear Local HTTP Authentication Cache</a>
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue