def check_login_required(): if not self.active: # not active, no handling return if flask.request.endpoint in ("api.login",): return if plugin is not None and not plugin.is_blueprint_protected(): return user = flask_login.current_user if user is None or user.is_anonymous() or not user.is_active(): return flask.make_response("Forbidden", 403)
def check_login_required(): if not self.active: # not active, no handling return if flask.request.endpoint in ("api.login", ): return if plugin is not None and not plugin.is_blueprint_protected(): return user = flask_login.current_user if user is None or user.is_anonymous() or not user.is_active(): return flask.make_response("Forbidden", 403)
def _register_blueprint_plugin(self, plugin): name = plugin._identifier blueprint = plugin.get_blueprint() if blueprint is None: return if plugin.is_blueprint_protected(): from octoprint.server.util import apiKeyRequestHandler, corsResponseHandler blueprint.before_request(apiKeyRequestHandler) blueprint.after_request(corsResponseHandler) url_prefix = "/plugin/{name}".format(name=name) app.register_blueprint(blueprint, url_prefix=url_prefix) if self._logger: self._logger.debug("Registered API of plugin {name} under URL prefix {url_prefix}".format(name=name, url_prefix=url_prefix))
class Server(): def __init__(self, configfile=None, basedir=None, host="0.0.0.0", port=5000, debug=False, allowRoot=False, logConf=None): self._configfile = configfile self._basedir = basedir self._host = host self._port = port self._debug = debug self._allowRoot = allowRoot self._logConf = logConf self._server = None def run(self): if not self._allowRoot: self._checkForRoot() global printer global printerProfileManager global fileManager global slicingManager global analysisQueue global userManager global eventManager global loginManager global pluginManager global appSessionManager global debug from tornado.ioloop import IOLoop from tornado.web import Application import sys debug = self._debug import subprocess cmd1 = "/usr/bin/reset_user_info.sh" subprocess.Popen(cmd1, shell=True) cmd2 = "echo heartbeat > /sys/class/leds/usr1/trigger" subprocess.Popen(cmd2, shell=True) import time time.sleep(0.5) # first initialize the settings singleton and make sure it uses given configfile and basedir if available self._initSettings(self._configfile, self._basedir) # then initialize logging self._initLogging(self._debug, self._logConf) logger = logging.getLogger(__name__) def exception_logger(exc_type, exc_value, exc_tb): logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_tb)) sys.excepthook = exception_logger logger.info("Starting OctoPrint %s" % DISPLAY_VERSION) # then initialize the plugin manager pluginManager = octoprint.plugin.plugin_manager(init=True) printerProfileManager = PrinterProfileManager() eventManager = events.eventManager() analysisQueue = octoprint.filemanager.analysis.AnalysisQueue() slicingManager = octoprint.slicing.SlicingManager( settings().getBaseFolder("slicingProfiles"), printerProfileManager) storage_managers = dict() storage_managers[ octoprint.filemanager.FileDestinations. LOCAL] = octoprint.filemanager.storage.LocalFileStorage( settings().getBaseFolder("uploads")) fileManager = octoprint.filemanager.FileManager( analysisQueue, slicingManager, printerProfileManager, initial_storage_managers=storage_managers) printer = Printer(fileManager, analysisQueue, printerProfileManager) appSessionManager = util.flask.AppSessionManager() # configure additional template folders for jinja2 template_plugins = pluginManager.get_implementations( octoprint.plugin.TemplatePlugin) additional_template_folders = [] for plugin in template_plugins.values(): folder = plugin.get_template_folder() if folder is not None: additional_template_folders.append( plugin.get_template_folder()) import jinja2 jinja_loader = jinja2.ChoiceLoader([ app.jinja_loader, jinja2.FileSystemLoader(additional_template_folders) ]) app.jinja_loader = jinja_loader del jinja2 # configure timelapse octoprint.timelapse.configureTimelapse() # setup command triggers events.CommandTrigger(printer) if self._debug: events.DebugEventListener() if settings().getBoolean(["accessControl", "enabled"]): userManagerName = settings().get(["accessControl", "userManager"]) try: clazz = octoprint.util.getClass(userManagerName) userManager = clazz() except AttributeError, e: logger.exception( "Could not instantiate user manager %s, will run with accessControl disabled!" % userManagerName) app.wsgi_app = util.ReverseProxied( app.wsgi_app, settings().get(["server", "reverseProxy", "prefixHeader"]), settings().get(["server", "reverseProxy", "schemeHeader"]), settings().get(["server", "reverseProxy", "hostHeader"]), settings().get(["server", "reverseProxy", "prefixFallback"]), settings().get(["server", "reverseProxy", "schemeFallback"]), settings().get(["server", "reverseProxy", "hostFallback"])) secret_key = settings().get(["server", "secretKey"]) if not secret_key: import string from random import choice chars = string.ascii_lowercase + string.ascii_uppercase + string.digits secret_key = "".join(choice(chars) for _ in xrange(32)) settings().set(["server", "secretKey"], secret_key) settings().save() app.secret_key = secret_key loginManager = LoginManager() loginManager.session_protection = "strong" loginManager.user_callback = load_user if userManager is None: loginManager.anonymous_user = users.DummyUser principals.identity_loaders.appendleft(users.dummy_identity_loader) loginManager.init_app(app) if self._host is None: self._host = settings().get(["server", "host"]) if self._port is None: self._port = settings().getInt(["server", "port"]) app.debug = self._debug from octoprint.server.api import api from octoprint.server.apps import apps # register API blueprint app.register_blueprint(api, url_prefix="/api") app.register_blueprint(apps, url_prefix="/apps") # also register any blueprints defined in BlueprintPlugins blueprint_plugins = octoprint.plugin.plugin_manager( ).get_implementations(octoprint.plugin.BlueprintPlugin) for name, plugin in blueprint_plugins.items(): blueprint = plugin.get_blueprint() if blueprint is None: continue if plugin.is_blueprint_protected(): from octoprint.server.util import apiKeyRequestHandler, corsResponseHandler blueprint.before_request(apiKeyRequestHandler) blueprint.after_request(corsResponseHandler) url_prefix = "/plugin/{name}".format(name=name) app.register_blueprint(blueprint, url_prefix=url_prefix) logger.debug( "Registered API of plugin {name} under URL prefix {url_prefix}" .format(name=name, url_prefix=url_prefix)) self._router = SockJSRouter(self._createSocketConnection, "/sockjs") upload_suffixes = dict( name=settings().get(["server", "uploads", "nameSuffix"]), path=settings().get(["server", "uploads", "pathSuffix"])) self._tornado_app = Application( self._router.urls + [(r"/downloadSD", util.tornado.LkjDownFileHandler), (r"/downloads/timelapse/([^/]*\.mpg)", util.tornado.LargeResponseHandler, dict(path=settings().getBaseFolder("timelapse"), as_attachment=True)), (r"/downloads/files/local/([^/]*\.(gco|gcode|g))", util.tornado.LargeResponseHandler, dict(path=settings().getBaseFolder("uploads"), as_attachment=True)), (r"/downloads/logs/([^/]*)", util.tornado.LargeResponseHandler, dict(path=settings().getBaseFolder("logs"), as_attachment=True, access_validation=util.tornado.access_validation_factory( app, loginManager, util.flask.admin_validator))), (r"/downloads/camera/current", util.tornado.UrlForwardHandler, dict(url=settings().get(["webcam", "snapshot"]), as_attachment=True, access_validation=util.tornado.access_validation_factory( app, loginManager, util.flask.user_validator))), (r".*", util.tornado.UploadStorageFallbackHandler, dict(fallback=util.tornado.WsgiInputContainer(app.wsgi_app), file_prefix="octoprint-file-upload-", file_suffix=".tmp", suffixes=upload_suffixes))]) max_body_sizes = [("POST", r"/api/files/([^/]*)", settings().getInt(["server", "uploads", "maxSize"]))] self._server = util.tornado.CustomHTTPServer( self._tornado_app, max_body_sizes=max_body_sizes, default_max_body_size=settings().getInt(["server", "maxSize"])) self._server.listen(self._port, address=self._host) eventManager.fire(events.Events.STARTUP) if settings().getBoolean(["serial", "autoconnect"]): (port, baudrate) = settings().get( ["serial", "port"]), settings().getInt(["serial", "baudrate"]) printer_profile = printerProfileManager.get_default() connectionOptions = getConnectionOptions() if port in connectionOptions["ports"]: printer.connect(transport_option_overrides=dict( port=port, baudrate=baudrate), profile=printer_profile["id"] if "id" in printer_profile else "_default") # start up watchdogs observer = Observer() observer.schedule( util.watchdog.GcodeWatchdogHandler(fileManager, printer), settings().getBaseFolder("watched")) observer.start() ioloop = IOLoop.instance() # run our startup plugins octoprint.plugin.call_plugin(octoprint.plugin.StartupPlugin, "on_startup", args=(self._host, self._port)) # prepare our after startup function def on_after_startup(): logger.info("Listening on http://%s:%d" % (self._host, self._port)) # now this is somewhat ugly, but the issue is the following: startup plugins might want to do things for # which they need the server to be already alive (e.g. for being able to resolve urls, such as favicons # or service xmls or the like). While they are working though the ioloop would block. Therefore we'll # create a single use thread in which to perform our after-startup-tasks, start that and hand back # control to the ioloop def work(): octoprint.plugin.call_plugin(octoprint.plugin.StartupPlugin, "on_after_startup") import threading threading.Thread(target=work).start() ioloop.add_callback(on_after_startup) # prepare our shutdown function def on_shutdown(): logger.info("Goodbye!") observer.stop() observer.join() octoprint.plugin.call_plugin(octoprint.plugin.ShutdownPlugin, "on_shutdown") atexit.register(on_shutdown) try: ioloop.start() except KeyboardInterrupt: pass except: logger.fatal( "Now that is embarrassing... Something really really went wrong here. Please report this including the stacktrace below in OctoPrint's bugtracker. Thanks!" ) logger.exception("Stacktrace follows:")