LocalAuthorizationServer.py 3.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. import threading
  4. from typing import Optional, Callable, Any, TYPE_CHECKING
  5. from UM.Logger import Logger
  6. from cura.OAuth2.AuthorizationRequestServer import AuthorizationRequestServer
  7. from cura.OAuth2.AuthorizationRequestHandler import AuthorizationRequestHandler
  8. if TYPE_CHECKING:
  9. from cura.OAuth2.Models import AuthenticationResponse
  10. from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
  11. class LocalAuthorizationServer:
  12. # The local LocalAuthorizationServer takes care of the oauth2 callbacks.
  13. # Once the flow is completed, this server should be closed down again by calling stop()
  14. # \param auth_helpers: An instance of the authorization helpers class.
  15. # \param auth_state_changed_callback: A callback function to be called when the authorization state changes.
  16. # \param daemon: Whether the server thread should be run in daemon mode. Note: Daemon threads are abruptly stopped
  17. # at shutdown. Their resources (e.g. open files) may never be released.
  18. def __init__(self, auth_helpers: "AuthorizationHelpers",
  19. auth_state_changed_callback: Callable[["AuthenticationResponse"], Any],
  20. daemon: bool) -> None:
  21. self._web_server = None # type: Optional[AuthorizationRequestServer]
  22. self._web_server_thread = None # type: Optional[threading.Thread]
  23. self._web_server_port = auth_helpers.settings.CALLBACK_PORT
  24. self._auth_helpers = auth_helpers
  25. self._auth_state_changed_callback = auth_state_changed_callback
  26. self._daemon = daemon
  27. # Starts the local web server to handle the authorization callback.
  28. # \param verification_code: The verification code part of the OAuth2 client identification.
  29. def start(self, verification_code: str) -> None:
  30. if self._web_server:
  31. # If the server is already running (because of a previously aborted auth flow), we don't have to start it.
  32. # We still inject the new verification code though.
  33. self._web_server.setVerificationCode(verification_code)
  34. return
  35. if self._web_server_port is None:
  36. raise Exception("Unable to start server without specifying the port.")
  37. Logger.log("d", "Starting local web server to handle authorization callback on port %s", self._web_server_port)
  38. # Create the server and inject the callback and code.
  39. self._web_server = AuthorizationRequestServer(("0.0.0.0", self._web_server_port), AuthorizationRequestHandler)
  40. self._web_server.setAuthorizationHelpers(self._auth_helpers)
  41. self._web_server.setAuthorizationCallback(self._auth_state_changed_callback)
  42. self._web_server.setVerificationCode(verification_code)
  43. # Start the server on a new thread.
  44. self._web_server_thread = threading.Thread(None, self._web_server.serve_forever, daemon = self._daemon)
  45. self._web_server_thread.start()
  46. # Stops the web server if it was running. It also does some cleanup.
  47. def stop(self) -> None:
  48. Logger.log("d", "Stopping local oauth2 web server...")
  49. if self._web_server:
  50. self._web_server.server_close()
  51. self._web_server = None
  52. self._web_server_thread = None