Slight refactoring of API key evaluation in restricted_access decorator

Actual test whether key is provided or not happens in before_request handler of flask app, hence the more granular processing in the decorator was unecessary since around november '14. Adjusted to only do the actual processing necessary to replicate login_required behaviour/login users if necessary.

Closes #516 (actually, that was solved since introduction of the before_request handler which took that work off the hands of the decorator, but now it's properly documented too)
This commit is contained in:
Gina Häußge 2015-06-03 11:55:32 +02:00
parent 27dcef3e23
commit d2bca10ac9
2 changed files with 26 additions and 24 deletions

View file

@ -5,13 +5,8 @@
### New Features
* Added internationalization of UI. Translations of OctoPrint are being crowd sourced via [Transifex](https://www.transifex.com/projects/p/octoprint/).
The following translations are already available with more in the works:
- Dutch (nl)
- German (de)
- French (fr)
- Hebrew (he)
- Norwegian (no)
- Romanian (ro)
Language Packs for both the core application as well as installed plugins can be uploaded through a new management
dialog in Settings > Appearance > Language Packs.
* New file list: Pagination is gone, no more (mobile incompatible) pop overs, instead scrollable and with instant
search
* You can now define a folder (default: `~/.octoprint/watched`) to be watched for newly added GCODE (or -- if slicing
@ -139,10 +134,11 @@
* [#435](https://github.com/foosel/OctoPrint/issues/435) - Always interpret negative duration (e.g. for print time left)
as 0
* [#633](https://github.com/foosel/OctoPrint/issues/633) - Correctly interpret temperature lines from multi extruder
setups under Smoothieware
* [#516](https://github.com/foosel/OctoPrint/issues/516) - Also require API key even if ACL is disabled.
* [#556](https://github.com/foosel/OctoPrint/issues/556) - Allow login of the same user from multiple browsers without
side effects
* [#633](https://github.com/foosel/OctoPrint/issues/633) - Correctly interpret temperature lines from multi extruder
setups under Smoothieware
* [#680](https://github.com/foosel/OctoPrint/issues/680) - Don't accidentally include a newline from the MIME headers
in the parsed multipart data from file uploads
* [#709](https://github.com/foosel/OctoPrint/issues/709) - Properly initialize time estimation for SD card transfers too

View file

@ -276,7 +276,7 @@ def redirect_to_tornado(request, target, code=302):
return flask.redirect(redirectUrl, code=code)
def restricted_access(func, api_enabled=True):
def restricted_access(func):
"""
If you decorate a view with this, it will ensure that first setup has been
done for OctoPrint's Access Control plus that any conditions of the
@ -288,11 +288,12 @@ def restricted_access(func, api_enabled=True):
that it's user database has been customized from default), the decorator
will cause a HTTP 403 status code to be returned by the decorated resource.
If an API key is provided and it matches a known key, the user will be logged in and
the view will be called directly. If the provided key doesn't match any known key,
a HTTP 403 status code will be returned by the decorated resource.
If the API key matches the UI API key, the result of calling login_required for the
view will be returned (browser session mode).
Otherwise the result of calling login_required will be returned.
Otherwise the API key will be attempted to be resolved to a user. If that is
successful the user will be logged in and the view will be called directly.
Otherwise a HTTP 401 status code will be returned.
"""
@functools.wraps(func)
def decorated_view(*args, **kwargs):
@ -300,19 +301,24 @@ def restricted_access(func, api_enabled=True):
if settings().getBoolean(["server", "firstRun"]) and (octoprint.server.userManager is None or not octoprint.server.userManager.hasBeenCustomized()):
return flask.make_response("OctoPrint isn't setup yet", 403)
# if API is globally enabled, enabled for this request and an api key is provided that is not the current UI API key, try to use that
apikey = octoprint.server.util.get_api_key(flask.request)
if settings().get(["api", "enabled"]) and api_enabled and apikey is not None and apikey != octoprint.server.UI_API_KEY:
user = octoprint.server.util.get_user_for_apikey(apikey)
if apikey == octoprint.server.UI_API_KEY:
# UI API key => call regular login_required decorator, we are using browser sessions here
return flask.ext.login.login_required(func)(*args, **kwargs)
if user is None:
return flask.make_response("Invalid API key", 401)
if flask.ext.login.login_user(user, remember=False):
flask.ext.principal.identity_changed.send(flask.current_app._get_current_object(), identity=flask.ext.principal.Identity(user.get_id()))
return func(*args, **kwargs)
# try to determine user for key
user = octoprint.server.util.get_user_for_apikey(apikey)
if user is None:
# no user or no key => go away
return flask.make_response("Invalid API key", 401)
if not flask.ext.login.login_user(user, remember=False):
# user for API key could not be logged in => go away
return flask.make_response("Invalid API key", 401)
flask.ext.principal.identity_changed.send(flask.current_app._get_current_object(), identity=flask.ext.principal.Identity(user.get_id()))
return func(*args, **kwargs)
# call regular login_required decorator
return flask.ext.login.login_required(func)(*args, **kwargs)
return decorated_view