Properly authenticate log file downloads on Tornado as well

Only allow for users with role admin.
This commit is contained in:
Gina Häußge 2014-02-24 14:13:55 +01:00
parent ace102e1c1
commit f844bd99c7
2 changed files with 27 additions and 4 deletions

View file

@ -2,6 +2,8 @@
__author__ = "Gina Häußge <osd@foosel.net>"
__license__ = 'GNU Affero General Public License http://www.gnu.org/licenses/agpl.html'
import flask
import tornado.wsgi
from sockjs.tornado import SockJSRouter
from flask import Flask, render_template, send_from_directory, make_response
from flask.ext.login import LoginManager
@ -27,7 +29,7 @@ principals = Principal(app)
admin_permission = Permission(RoleNeed("admin"))
user_permission = Permission(RoleNeed("user"))
# only import the octoprint stuff down here, as it might depend on things defined above to be initialized already
from octoprint.server.util import LargeResponseHandler, ReverseProxied, restricted_access, PrinterStateConnection, admin_validator
from octoprint.printer import Printer, getConnectionOptions
from octoprint.settings import settings
@ -174,10 +176,23 @@ class Server():
self._router = SockJSRouter(self._createSocketConnection, "/sockjs")
def admin_access_validation(request):
"""
Creates a custom wsgi and Flask request context in order to be able to process user information
stored in the current session.
:param request: The Tornado request for which to create the environment and context
"""
wsgi_environ = tornado.wsgi.WSGIContainer.environ(request)
with app.request_context(wsgi_environ):
app.session_interface.open_session(app, flask.request)
loginManager.reload_user()
admin_validator(flask.request)
self._tornado_app = Application(self._router.urls + [
(r"/downloads/timelapse/([^/]*\.mpg)", LargeResponseHandler, {"path": settings().getBaseFolder("timelapse"), "as_attachment": True}),
(r"/downloads/files/local/([^/]*\.(gco|gcode))", LargeResponseHandler, {"path": settings().getBaseFolder("uploads"), "as_attachment": True}),
(r"/downloads/logs/([^/]*)", LargeResponseHandler, {"path": settings().getBaseFolder("logs"), "as_attachment": True}),
(r"/downloads/logs/([^/]*)", LargeResponseHandler, {"path": settings().getBaseFolder("logs"), "as_attachment": True, "access_validation": admin_access_validation}),
(r".*", FallbackHandler, {"fallback": WSGIContainer(app.wsgi_app)})
])
self._server = HTTPServer(self._tornado_app)

View file

@ -303,11 +303,19 @@ class LargeResponseHandler(StaticFileHandler):
self.set_header("Content-Disposition", "attachment")
#~~ admin access validator for tornado
#~~ admin access validator for use with tornado
# TODO doesnt work for flask right now (no app context of course), try to figure out something
def admin_validator(request):
"""
Validates that the given request is made by an admin user, identified either by API key or existing Flask
session.
Must be executed in an existing Flask request context!
:param request: The Flask request object
"""
apikey = _getApiKey(request)
if settings().get(["api", "enabled"]) and apikey is not None:
user = _getUserForApiKey(apikey)