New hook octoprint.accesscontrol.keyvalidator
Allows plugins to provide their own API keys which then can be validated/translated into a User instance via this hook.
This commit is contained in:
parent
a9819cc2f9
commit
e7b455f880
2 changed files with 64 additions and 11 deletions
|
|
@ -226,6 +226,37 @@ octoprint.accesscontrol.appkey
|
|||
:return: A list of 3-tuples as described above
|
||||
:rtype: list
|
||||
|
||||
.. _sec-plugins-hook-accesscontrol-keyvalidator:
|
||||
|
||||
octoprint.accesscontrol.keyvalidator
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. py:function:: acl_keyvalidator_hook(apikey, *args, **kwargs)
|
||||
|
||||
Via this hook plugins may validate their own customized API keys to be used to access OctoPrint's API.
|
||||
|
||||
``apikey`` will be the API key as read from the request headers.
|
||||
|
||||
Hook handlers are expected to return a :class:`~octoprint.users.User` instance here that will then be considered that
|
||||
user making the request. By returning ``None`` or nothing at all, hook handlers signal that they do not handle the
|
||||
provided key.
|
||||
|
||||
**Example:**
|
||||
|
||||
Allows using a user's id as their API key (for obvious reasons this is NOT recommended in production environments
|
||||
and merely provided for educational purposes):
|
||||
|
||||
.. onlineinclude:: https://raw.githubusercontent.com/OctoPrint/Plugin-Examples/master/custom_keyvalidator.py
|
||||
:linenos:
|
||||
:tab-width: 4
|
||||
:caption: `custom_keyvalidator.py <https://github.com/OctoPrint/Plugin-Examples/blob/master/custom_keyvalidator.py>`_
|
||||
|
||||
.. versionadded:: 1.3.6
|
||||
|
||||
:param str apikey: The API key to validate
|
||||
:return: The user in whose name the request will be processed further
|
||||
:rtype: :class:`~octoprint.users.User`
|
||||
|
||||
.. _sec-plugins-hook-cli-commands:
|
||||
|
||||
octoprint.cli.commands
|
||||
|
|
|
|||
|
|
@ -11,8 +11,10 @@ import octoprint.server
|
|||
from octoprint.users import ApiUser
|
||||
|
||||
from octoprint.util import deprecated
|
||||
from octoprint.plugin import plugin_manager
|
||||
|
||||
import flask as _flask
|
||||
import logging
|
||||
|
||||
from . import flask
|
||||
from . import sockjs
|
||||
|
|
@ -55,14 +57,22 @@ def loginFromApiKeyRequestHandler():
|
|||
"""
|
||||
|
||||
apikey = get_api_key(_flask.request)
|
||||
|
||||
if apikey and apikey != octoprint.server.UI_API_KEY and not octoprint.server.appSessionManager.validate(apikey):
|
||||
user = get_user_for_apikey(apikey)
|
||||
if user is not None and _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()))
|
||||
else:
|
||||
return _flask.make_response("Invalid API key", 401)
|
||||
|
||||
if not apikey:
|
||||
return
|
||||
|
||||
if apikey == octoprint.server.UI_API_KEY:
|
||||
return
|
||||
|
||||
if octoprint.server.appSessionManager.validate(apikey):
|
||||
return
|
||||
|
||||
user = get_user_for_apikey(apikey)
|
||||
if user is not None and _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()))
|
||||
else:
|
||||
return _flask.make_response("Invalid API key", 401)
|
||||
|
||||
|
||||
def corsRequestHandler():
|
||||
|
|
@ -143,9 +153,21 @@ def get_user_for_apikey(apikey):
|
|||
if apikey == settings().get(["api", "key"]) or octoprint.server.appSessionManager.validate(apikey):
|
||||
# master key or an app session key was used
|
||||
return ApiUser()
|
||||
elif octoprint.server.userManager.enabled:
|
||||
# user key might have been used
|
||||
return octoprint.server.userManager.findUser(apikey=apikey)
|
||||
|
||||
if octoprint.server.userManager.enabled:
|
||||
user = octoprint.server.userManager.findUser(apikey=apikey)
|
||||
if user is not None:
|
||||
# user key was used
|
||||
return user
|
||||
|
||||
apikey_hooks = plugin_manager().get_hooks("octoprint.accesscontrol.keyvalidator")
|
||||
for name, hook in apikey_hooks.items():
|
||||
try:
|
||||
user = hook(apikey)
|
||||
if user is not None:
|
||||
return user
|
||||
except:
|
||||
logging.getLogger(__name__).exception("Error running api key validator for plugin {} and key {}".format(name, apikey))
|
||||
return None
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue