Merged in feature/HTTPASTE-46/view (pull request #50)
Feature/HTTPASTE-46/view
This commit is contained in:
commit
389571522f
16 changed files with 145 additions and 23 deletions
|
|
@ -14,7 +14,7 @@ WORKDIR /usr/local/src/httpaste
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y libffi-dev gcc && \
|
apt-get install -y libffi-dev gcc fontconfig && \
|
||||||
python3 -m pip install pipenv && \
|
python3 -m pip install pipenv && \
|
||||||
python3 -m pipenv install --deploy --system --verbose && \
|
python3 -m pipenv install --deploy --system --verbose && \
|
||||||
python3 setup.py install && \
|
python3 setup.py install && \
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ services:
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
volumes:
|
volumes:
|
||||||
-
|
-
|
||||||
type: volume
|
type: volume
|
||||||
|
|
@ -30,11 +31,13 @@ services:
|
||||||
volume:
|
volume:
|
||||||
nocopy: true
|
nocopy: true
|
||||||
- ./httpd/usr/local/apache2/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf
|
- ./httpd/usr/local/apache2/conf/httpd.conf:/usr/local/apache2/conf/httpd.conf
|
||||||
|
- ./httpd/usr/local/apache2/ssl:/usr/local/apache2/ssl
|
||||||
tor:
|
tor:
|
||||||
build:
|
build:
|
||||||
context: ./tor
|
context: ./tor
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
volumes:
|
volumes:
|
||||||
- ./tor/etc/tor/torrc:/etc/tor/torrc
|
- ./tor/etc/tor/torrc:/etc/tor/torrc
|
||||||
|
- ./tor/var/lib/tor/hidden_service:./tor/var/lib/tor/hidden_service
|
||||||
volumes:
|
volumes:
|
||||||
system-shared:
|
system-shared:
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ LoadModule unixd_module modules/mod_unixd.so
|
||||||
LoadModule access_compat_module modules/mod_access_compat.so
|
LoadModule access_compat_module modules/mod_access_compat.so
|
||||||
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so
|
LoadModule security2_module /usr/lib/apache2/modules/mod_security2.so
|
||||||
LoadModule evasive20_module /usr/lib/apache2/modules/mod_evasive20.so
|
LoadModule evasive20_module /usr/lib/apache2/modules/mod_evasive20.so
|
||||||
|
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
|
||||||
|
|
||||||
<IfModule unixd_module>
|
<IfModule unixd_module>
|
||||||
User www-data
|
User www-data
|
||||||
|
|
@ -88,3 +88,20 @@ ServerName 127.0.0.1
|
||||||
SetEnv proxy-sendchunks
|
SetEnv proxy-sendchunks
|
||||||
ProxyPass "/" "unix:/shared/uwsgi.sock|uwsgi://localhost/"
|
ProxyPass "/" "unix:/shared/uwsgi.sock|uwsgi://localhost/"
|
||||||
</VirtualHost>
|
</VirtualHost>
|
||||||
|
|
||||||
|
<IfFile 'ssl/private.key'>
|
||||||
|
Listen 0.0.0.0:443
|
||||||
|
|
||||||
|
|
||||||
|
<VirtualHost 0.0.0.0:443>
|
||||||
|
#ProxyPreserveHost On
|
||||||
|
ServerName httpaste.it
|
||||||
|
ServerAlias localhost
|
||||||
|
SSLEngine on
|
||||||
|
SSLCertificateFile "ssl/certificate.crt"
|
||||||
|
SSLCertificateChainFile "ssl/ca_bundle.crt"
|
||||||
|
SSLCertificateKeyFile "ssl/private.key"
|
||||||
|
SetEnv proxy-sendchunks
|
||||||
|
ProxyPass "/" "unix:/shared/uwsgi.sock|uwsgi://localhost/"
|
||||||
|
</VirtualHost>
|
||||||
|
</IfFile>
|
||||||
|
|
|
||||||
2
samples/httpaste.it/httpd/usr/local/apache2/ssl/.gitignore
vendored
Normal file
2
samples/httpaste.it/httpd/usr/local/apache2/ssl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
*.key
|
||||||
|
*.crt
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
*
|
||||||
|
|
@ -152,6 +152,7 @@ from httpaste.model import Config as ModelConfig
|
||||||
from httpaste.backend import get_backend_config
|
from httpaste.backend import get_backend_config
|
||||||
from httpaste.backend import Config as BackendConfig
|
from httpaste.backend import Config as BackendConfig
|
||||||
from httpaste.helper.config import get_configparser, CONFIGPATH_ENVIRON
|
from httpaste.helper.config import get_configparser, CONFIGPATH_ENVIRON
|
||||||
|
from httpaste.helper.url import url_upgrade_to_https
|
||||||
from httpaste.helper.http import (
|
from httpaste.helper.http import (
|
||||||
BadRequestError,
|
BadRequestError,
|
||||||
ForbiddenError,
|
ForbiddenError,
|
||||||
|
|
@ -201,8 +202,6 @@ def get_flask_app(config: Config) -> FlaskApp:
|
||||||
"""get a flask app object
|
"""get a flask app object
|
||||||
"""
|
"""
|
||||||
|
|
||||||
print(config.server.swagger_ui)
|
|
||||||
|
|
||||||
options = {"swagger_ui": config.server.swagger_ui}
|
options = {"swagger_ui": config.server.swagger_ui}
|
||||||
|
|
||||||
#context manager returns a pathlib.Path object
|
#context manager returns a pathlib.Path object
|
||||||
|
|
@ -238,6 +237,20 @@ def get_flask_app(config: Config) -> FlaskApp:
|
||||||
response.headers['WWW-Authenticate'] = 'Basic realm="private"'
|
response.headers['WWW-Authenticate'] = 'Basic realm="private"'
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
@application.app.before_request
|
||||||
|
def before_request_func():
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
request._view = {}
|
||||||
|
|
||||||
|
if config.server.request_ssl:
|
||||||
|
|
||||||
|
https_url = url_upgrade_to_https(request.url, config.server.ssl_port)
|
||||||
|
|
||||||
|
if https_url != request.url:
|
||||||
|
|
||||||
|
request._view['before_request__ssl_url'] = https_url
|
||||||
|
|
||||||
return application
|
return application
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
from httpaste.helper.template import views
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
from httpaste import __doc__ as man_page
|
from httpaste import __doc__ as man_page
|
||||||
|
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
def search(**kwargs):
|
def search(**kwargs):
|
||||||
|
|
||||||
template = views.get_template("viewport/ui/search.html")
|
template = views.get_template("viewport/ui/search.html")
|
||||||
|
|
@ -13,4 +15,7 @@ def search(**kwargs):
|
||||||
'delete_session_url': '/ui/user/session/delete'
|
'delete_session_url': '/ui/user/session/delete'
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
@ -2,8 +2,9 @@ from io import BytesIO
|
||||||
from base64 import b64encode
|
from base64 import b64encode
|
||||||
|
|
||||||
from connexion import request
|
from connexion import request
|
||||||
|
from flask import current_app
|
||||||
|
|
||||||
from httpaste.helper.template import views
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
from httpaste.helper.url import url_query_string, url_append_query_param
|
from httpaste.helper.url import url_query_string, url_append_query_param
|
||||||
from httpaste.helper.syntax import syntax_shortnames, format_shortnames
|
from httpaste.helper.syntax import syntax_shortnames, format_shortnames
|
||||||
from httpaste.helper.http import mime_types
|
from httpaste.helper.http import mime_types
|
||||||
|
|
@ -23,7 +24,10 @@ def search(**kwargs):
|
||||||
'delete_session_url': '/ui/user/session/delete'
|
'delete_session_url': '/ui/user/session/delete'
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
||||||
|
|
||||||
def post(**kwargs):
|
def post(**kwargs):
|
||||||
|
|
@ -93,4 +97,7 @@ def get(**kwargs):
|
||||||
'mime_types': mime_types()
|
'mime_types': mime_types()
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables)
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
from httpaste.helper.template import views
|
from flask import current_app
|
||||||
|
|
||||||
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
from httpaste.controller.ui.paste import post as post_proxy
|
from httpaste.controller.ui.paste import post as post_proxy
|
||||||
from httpaste.controller.ui.paste import get as get_proxy
|
from httpaste.controller.ui.paste import get as get_proxy
|
||||||
|
|
||||||
|
|
@ -8,10 +10,12 @@ def search(**kwargs):
|
||||||
|
|
||||||
variables = {
|
variables = {
|
||||||
'paste_form_url': '/ui/paste/private',
|
'paste_form_url': '/ui/paste/private',
|
||||||
'user': kwargs.get('user')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
||||||
|
|
||||||
def post(**kwargs):
|
def post(**kwargs):
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
from httpaste.helper.template import views
|
from flask import current_app
|
||||||
|
|
||||||
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
from httpaste.controller.ui.paste import post as post_proxy
|
from httpaste.controller.ui.paste import post as post_proxy
|
||||||
from httpaste.controller.ui.paste import get as get_proxy
|
from httpaste.controller.ui.paste import get as get_proxy
|
||||||
|
|
||||||
|
|
@ -10,7 +12,10 @@ def search(**kwargs):
|
||||||
'paste_form_url': '/ui/paste/public'
|
'paste_form_url': '/ui/paste/public'
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
||||||
|
|
||||||
def post(**kwargs):
|
def post(**kwargs):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from httpaste.helper.template import views
|
from flask import current_app
|
||||||
from httpaste import __doc__ as man_page
|
|
||||||
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
|
|
||||||
def search(**kwargs):
|
def search(**kwargs):
|
||||||
|
|
||||||
|
|
@ -9,4 +10,7 @@ def search(**kwargs):
|
||||||
'delete_session_url': '/ui/user/session/delete'
|
'delete_session_url': '/ui/user/session/delete'
|
||||||
}
|
}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
from httpaste.helper.template import views
|
from httpaste.helper.template import views, render_template_with_context
|
||||||
from httpaste.controller.user.session import delete as raw_delete
|
from httpaste.controller.user.session import delete as raw_delete
|
||||||
|
|
||||||
from connexion import request
|
from connexion import request
|
||||||
|
|
@ -7,11 +7,12 @@ def search(**kwargs):
|
||||||
|
|
||||||
template = views.get_template("viewport/ui/user/session/search.html")
|
template = views.get_template("viewport/ui/user/session/search.html")
|
||||||
|
|
||||||
print(request.path)
|
|
||||||
|
|
||||||
variables = {'session_delete_url': request.path + '/delete'}
|
variables = {'session_delete_url': request.path + '/delete'}
|
||||||
|
|
||||||
return template.render(**variables), 200
|
with current_app.app_context():
|
||||||
|
view_render = render_template_with_context(template, **variables)
|
||||||
|
|
||||||
|
return view_render, 200
|
||||||
|
|
||||||
|
|
||||||
def delete(**kwargs):
|
def delete(**kwargs):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,25 @@
|
||||||
from jinja2 import Environment, PackageLoader, select_autoescape
|
from jinja2 import Environment, PackageLoader, select_autoescape
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
views = Environment(
|
views = Environment(
|
||||||
loader=PackageLoader("httpaste", "view"),
|
loader=PackageLoader("httpaste", "view"),
|
||||||
autoescape=select_autoescape()
|
autoescape=select_autoescape()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def render_template_with_context(template: object, **kwargs):
|
||||||
|
"""render a template with global context variables
|
||||||
|
|
||||||
|
the definition of a global context is abstract, it does neither apply
|
||||||
|
to Flask, nor to Jinja2 and only acts as a bridge for passing
|
||||||
|
variables from flask to jinja2, without having to define them within
|
||||||
|
each controller.
|
||||||
|
|
||||||
|
:param template: jinja2 template object
|
||||||
|
"""
|
||||||
|
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
return template.render(**{**kwargs, **{
|
||||||
|
'flask': namedtuple('Flask', request._view.keys())(**request._view)
|
||||||
|
}})
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
from typing import Optional
|
||||||
from urllib.parse import urlparse, parse_qs
|
from urllib.parse import urlparse, parse_qs
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -18,3 +19,22 @@ def url_append_query_param(url:str, name: str, value:str):
|
||||||
|
|
||||||
return urlcomps._replace(query=qs).geturl()
|
return urlcomps._replace(query=qs).geturl()
|
||||||
|
|
||||||
|
|
||||||
|
def url_upgrade_to_https(url: str, port: Optional[int] = 443):
|
||||||
|
|
||||||
|
urlcomps = urlparse(url)
|
||||||
|
|
||||||
|
urlcomps = urlcomps._replace(scheme='https')
|
||||||
|
|
||||||
|
if url != urlcomps.geturl():
|
||||||
|
|
||||||
|
hostname = urlcomps.netloc.rsplit(':', 1)[0]
|
||||||
|
|
||||||
|
if port != 443:
|
||||||
|
netloc = ':'.join((hostname, str(port)))
|
||||||
|
else:
|
||||||
|
netloc = hostname
|
||||||
|
|
||||||
|
urlcomps = urlcomps._replace(netloc=netloc)
|
||||||
|
|
||||||
|
return urlcomps.geturl()
|
||||||
|
|
@ -10,6 +10,8 @@ class Config(NamedTuple):
|
||||||
"""
|
"""
|
||||||
swagger_ui: bool = True
|
swagger_ui: bool = True
|
||||||
bind_address: str = None
|
bind_address: str = None
|
||||||
|
request_ssl: bool = True
|
||||||
|
ssl_port: int = 443
|
||||||
|
|
||||||
|
|
||||||
def get_server_config(configIni: ConfigParser) -> Config:
|
def get_server_config(configIni: ConfigParser) -> Config:
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,29 @@
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.blinking{
|
||||||
|
animation:blinkingText 1.0s infinite;
|
||||||
|
animation-timing-function: step-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.warning {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes blinkingText {
|
||||||
|
0%{ color: red; }
|
||||||
|
50%{ color: transparent; }
|
||||||
|
100%{ color: red; }
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<header>
|
<header>
|
||||||
|
{% if flask.before_request__ssl_url is defined %}
|
||||||
|
<p>
|
||||||
|
<strong class="blinking warning">WARNING:</strong> Communication not encrypted - SSL/TLS will not be enforced. Visit <a href="{{ flask.before_request__ssl_url }}">{{ flask.before_request__ssl_url }}</a>, for SSL/TLS encryption.
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
{% block header %}{% endblock %}
|
{% block header %}{% endblock %}
|
||||||
</header>
|
</header>
|
||||||
<hr/>
|
<hr/>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue