mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-08 15:37:27 -06:00
Fix number of mypy mistakes
CURA-5744
This commit is contained in:
parent
3ae223334f
commit
d0fc4878c2
5 changed files with 33 additions and 20 deletions
|
@ -16,7 +16,7 @@ from cura.OAuth2.Models import AuthenticationResponse, UserProfile, OAuth2Settin
|
||||||
class AuthorizationHelpers:
|
class AuthorizationHelpers:
|
||||||
"""Class containing several helpers to deal with the authorization flow."""
|
"""Class containing several helpers to deal with the authorization flow."""
|
||||||
|
|
||||||
def __init__(self, settings: "OAuth2Settings"):
|
def __init__(self, settings: "OAuth2Settings") -> None:
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._token_url = "{}/token".format(self._settings.OAUTH_SERVER_URL)
|
self._token_url = "{}/token".format(self._settings.OAUTH_SERVER_URL)
|
||||||
|
|
||||||
|
@ -25,8 +25,7 @@ class AuthorizationHelpers:
|
||||||
"""Get the OAuth2 settings object."""
|
"""Get the OAuth2 settings object."""
|
||||||
return self._settings
|
return self._settings
|
||||||
|
|
||||||
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str)->\
|
def getAccessTokenUsingAuthorizationCode(self, authorization_code: str, verification_code: str)-> "AuthenticationResponse":
|
||||||
Optional["AuthenticationResponse"]:
|
|
||||||
"""
|
"""
|
||||||
Request the access token from the authorization server.
|
Request the access token from the authorization server.
|
||||||
:param authorization_code: The authorization code from the 1st step.
|
:param authorization_code: The authorization code from the 1st step.
|
||||||
|
@ -42,7 +41,7 @@ class AuthorizationHelpers:
|
||||||
"scope": self._settings.CLIENT_SCOPES
|
"scope": self._settings.CLIENT_SCOPES
|
||||||
}))
|
}))
|
||||||
|
|
||||||
def getAccessTokenUsingRefreshToken(self, refresh_token: str) -> Optional["AuthenticationResponse"]:
|
def getAccessTokenUsingRefreshToken(self, refresh_token: str) -> AuthenticationResponse:
|
||||||
"""
|
"""
|
||||||
Request the access token from the authorization server using a refresh token.
|
Request the access token from the authorization server using a refresh token.
|
||||||
:param refresh_token:
|
:param refresh_token:
|
||||||
|
@ -57,7 +56,7 @@ class AuthorizationHelpers:
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parseTokenResponse(token_response: "requests.request") -> Optional["AuthenticationResponse"]:
|
def parseTokenResponse(token_response: requests.models.Response) -> AuthenticationResponse:
|
||||||
"""
|
"""
|
||||||
Parse the token response from the authorization server into an AuthenticationResponse object.
|
Parse the token response from the authorization server into an AuthenticationResponse object.
|
||||||
:param token_response: The JSON string data response from the authorization server.
|
:param token_response: The JSON string data response from the authorization server.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Copyright (c) 2018 Ultimaker B.V.
|
# Copyright (c) 2018 Ultimaker B.V.
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
from typing import Optional, Callable
|
from typing import Optional, Callable, Tuple, Dict, Any, List
|
||||||
|
|
||||||
from http.server import BaseHTTPRequestHandler
|
from http.server import BaseHTTPRequestHandler
|
||||||
from urllib.parse import parse_qs, urlparse
|
from urllib.parse import parse_qs, urlparse
|
||||||
|
@ -49,16 +49,17 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
||||||
# This will cause the server to shut down, so we do it at the very end of the request handling.
|
# This will cause the server to shut down, so we do it at the very end of the request handling.
|
||||||
self.authorization_callback(token_response)
|
self.authorization_callback(token_response)
|
||||||
|
|
||||||
def _handleCallback(self, query: dict) -> ("ResponseData", Optional["AuthenticationResponse"]):
|
def _handleCallback(self, query: Dict[Any, List]) -> Tuple["ResponseData", Optional["AuthenticationResponse"]]:
|
||||||
"""
|
"""
|
||||||
Handler for the callback URL redirect.
|
Handler for the callback URL redirect.
|
||||||
:param query: Dict containing the HTTP query parameters.
|
:param query: Dict containing the HTTP query parameters.
|
||||||
:return: HTTP ResponseData containing a success page to show to the user.
|
:return: HTTP ResponseData containing a success page to show to the user.
|
||||||
"""
|
"""
|
||||||
if self._queryGet(query, "code"):
|
code = self._queryGet(query, "code")
|
||||||
|
if code:
|
||||||
# If the code was returned we get the access token.
|
# If the code was returned we get the access token.
|
||||||
token_response = self.authorization_helpers.getAccessTokenUsingAuthorizationCode(
|
token_response = self.authorization_helpers.getAccessTokenUsingAuthorizationCode(
|
||||||
self._queryGet(query, "code"), self.verification_code)
|
code, self.verification_code)
|
||||||
|
|
||||||
elif self._queryGet(query, "error_code") == "user_denied":
|
elif self._queryGet(query, "error_code") == "user_denied":
|
||||||
# Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
|
# Otherwise we show an error message (probably the user clicked "Deny" in the auth dialog).
|
||||||
|
@ -99,6 +100,6 @@ class AuthorizationRequestHandler(BaseHTTPRequestHandler):
|
||||||
self.wfile.write(data)
|
self.wfile.write(data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _queryGet(query_data: dict, key: str, default=None) -> Optional[str]:
|
def _queryGet(query_data: Dict[Any, List], key: str, default=None) -> Optional[str]:
|
||||||
"""Helper for getting values from a pre-parsed query string"""
|
"""Helper for getting values from a pre-parsed query string"""
|
||||||
return query_data.get(key, [default])[0]
|
return query_data.get(key, [default])[0]
|
||||||
|
|
|
@ -27,7 +27,7 @@ class AuthorizationService:
|
||||||
# Emit signal when authentication failed.
|
# Emit signal when authentication failed.
|
||||||
onAuthenticationError = Signal()
|
onAuthenticationError = Signal()
|
||||||
|
|
||||||
def __init__(self, preferences, settings: "OAuth2Settings"):
|
def __init__(self, preferences, settings: "OAuth2Settings") -> None:
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._auth_helpers = AuthorizationHelpers(settings)
|
self._auth_helpers = AuthorizationHelpers(settings)
|
||||||
self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL)
|
self._auth_url = "{}/authorize".format(self._settings.OAUTH_SERVER_URL)
|
||||||
|
@ -55,7 +55,7 @@ class AuthorizationService:
|
||||||
Tries to parse the JWT if all the needed data exists.
|
Tries to parse the JWT if all the needed data exists.
|
||||||
:return: UserProfile if found, otherwise None.
|
:return: UserProfile if found, otherwise None.
|
||||||
"""
|
"""
|
||||||
if not self._auth_data:
|
if not self._auth_data or self._auth_data.access_token is None:
|
||||||
# If no auth data exists, we should always log in again.
|
# If no auth data exists, we should always log in again.
|
||||||
return None
|
return None
|
||||||
user_data = self._auth_helpers.parseJWT(self._auth_data.access_token)
|
user_data = self._auth_helpers.parseJWT(self._auth_data.access_token)
|
||||||
|
@ -63,10 +63,13 @@ class AuthorizationService:
|
||||||
# If the profile was found, we return it immediately.
|
# If the profile was found, we return it immediately.
|
||||||
return user_data
|
return user_data
|
||||||
# The JWT was expired or invalid and we should request a new one.
|
# The JWT was expired or invalid and we should request a new one.
|
||||||
|
if self._auth_data.refresh_token is None:
|
||||||
|
return None
|
||||||
self._auth_data = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
|
self._auth_data = self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token)
|
||||||
if not self._auth_data:
|
if not self._auth_data or self._auth_data.access_token is None:
|
||||||
# The token could not be refreshed using the refresh token. We should login again.
|
# The token could not be refreshed using the refresh token. We should login again.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self._auth_helpers.parseJWT(self._auth_data.access_token)
|
return self._auth_helpers.parseJWT(self._auth_data.access_token)
|
||||||
|
|
||||||
def getAccessToken(self) -> Optional[str]:
|
def getAccessToken(self) -> Optional[str]:
|
||||||
|
@ -78,16 +81,23 @@ class AuthorizationService:
|
||||||
# We check if we can get the user profile.
|
# We check if we can get the user profile.
|
||||||
# If we can't get it, that means the access token (JWT) was invalid or expired.
|
# If we can't get it, that means the access token (JWT) was invalid or expired.
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if self._auth_data is None:
|
||||||
|
return None
|
||||||
|
|
||||||
return self._auth_data.access_token
|
return self._auth_data.access_token
|
||||||
|
|
||||||
def refreshAccessToken(self) -> None:
|
def refreshAccessToken(self) -> None:
|
||||||
"""
|
"""
|
||||||
Refresh the access token when it expired.
|
Refresh the access token when it expired.
|
||||||
"""
|
"""
|
||||||
|
if self._auth_data is None or self._auth_data.refresh_token is None:
|
||||||
|
Logger.log("w", "Unable to refresh acces token, since there is no refresh token.")
|
||||||
|
return
|
||||||
self._storeAuthData(self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token))
|
self._storeAuthData(self._auth_helpers.getAccessTokenUsingRefreshToken(self._auth_data.refresh_token))
|
||||||
self.onAuthStateChanged.emit(logged_in=True)
|
self.onAuthStateChanged.emit(logged_in=True)
|
||||||
|
|
||||||
def deleteAuthData(self):
|
def deleteAuthData(self) -> None:
|
||||||
"""Delete authentication data from preferences and locally."""
|
"""Delete authentication data from preferences and locally."""
|
||||||
self._storeAuthData()
|
self._storeAuthData()
|
||||||
self.onAuthStateChanged.emit(logged_in=False)
|
self.onAuthStateChanged.emit(logged_in=False)
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
# Cura is released under the terms of the LGPLv3 or higher.
|
# Cura is released under the terms of the LGPLv3 or higher.
|
||||||
import threading
|
import threading
|
||||||
from http.server import HTTPServer
|
from http.server import HTTPServer
|
||||||
from typing import Optional, Callable
|
from typing import Optional, Callable, Any
|
||||||
|
|
||||||
# As this module is specific for Cura plugins, we can rely on these imports.
|
# As this module is specific for Cura plugins, we can rely on these imports.
|
||||||
from UM.Logger import Logger
|
from UM.Logger import Logger
|
||||||
|
@ -16,22 +16,22 @@ from cura.OAuth2.Models import AuthenticationResponse
|
||||||
|
|
||||||
class LocalAuthorizationServer:
|
class LocalAuthorizationServer:
|
||||||
def __init__(self, auth_helpers: "AuthorizationHelpers",
|
def __init__(self, auth_helpers: "AuthorizationHelpers",
|
||||||
auth_state_changed_callback: "Callable[[AuthenticationResponse], any]",
|
auth_state_changed_callback: "Callable[[AuthenticationResponse], Any]",
|
||||||
daemon: bool):
|
daemon: bool) -> None:
|
||||||
"""
|
"""
|
||||||
:param auth_helpers: An instance of the authorization helpers class.
|
:param auth_helpers: An instance of the authorization helpers class.
|
||||||
:param auth_state_changed_callback: A callback function to be called when the authorization state changes.
|
:param auth_state_changed_callback: A callback function to be called when the authorization state changes.
|
||||||
:param daemon: Whether the server thread should be run in daemon mode. Note: Daemon threads are abruptly stopped
|
:param daemon: Whether the server thread should be run in daemon mode. Note: Daemon threads are abruptly stopped
|
||||||
at shutdown. Their resources (e.g. open files) may never be released.
|
at shutdown. Their resources (e.g. open files) may never be released.
|
||||||
"""
|
"""
|
||||||
self._web_server = None # type: Optional[HTTPServer]
|
self._web_server = None # type: Optional[AuthorizationRequestServer]
|
||||||
self._web_server_thread = None # type: Optional[threading.Thread]
|
self._web_server_thread = None # type: Optional[threading.Thread]
|
||||||
self._web_server_port = auth_helpers.settings.CALLBACK_PORT
|
self._web_server_port = auth_helpers.settings.CALLBACK_PORT
|
||||||
self._auth_helpers = auth_helpers
|
self._auth_helpers = auth_helpers
|
||||||
self._auth_state_changed_callback = auth_state_changed_callback
|
self._auth_state_changed_callback = auth_state_changed_callback
|
||||||
self._daemon = daemon
|
self._daemon = daemon
|
||||||
|
|
||||||
def start(self, verification_code: "str") -> None:
|
def start(self, verification_code: str) -> None:
|
||||||
"""
|
"""
|
||||||
Starts the local web server to handle the authorization callback.
|
Starts the local web server to handle the authorization callback.
|
||||||
:param verification_code: The verification code part of the OAuth2 client identification.
|
:param verification_code: The verification code part of the OAuth2 client identification.
|
||||||
|
@ -42,6 +42,9 @@ class LocalAuthorizationServer:
|
||||||
self._web_server.setVerificationCode(verification_code)
|
self._web_server.setVerificationCode(verification_code)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self._web_server_port is None:
|
||||||
|
raise Exception("Unable to start server without specifying the port.")
|
||||||
|
|
||||||
Logger.log("d", "Starting local web server to handle authorization callback on port %s",
|
Logger.log("d", "Starting local web server to handle authorization callback on port %s",
|
||||||
self._web_server_port)
|
self._web_server_port)
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ class BaseModel:
|
||||||
|
|
||||||
# OAuth OAuth2Settings data template.
|
# OAuth OAuth2Settings data template.
|
||||||
class OAuth2Settings(BaseModel):
|
class OAuth2Settings(BaseModel):
|
||||||
CALLBACK_PORT = None # type: Optional[str]
|
CALLBACK_PORT = None # type: Optional[int]
|
||||||
OAUTH_SERVER_URL = None # type: Optional[str]
|
OAUTH_SERVER_URL = None # type: Optional[str]
|
||||||
CLIENT_ID = None # type: Optional[str]
|
CLIENT_ID = None # type: Optional[str]
|
||||||
CLIENT_SCOPES = None # type: Optional[str]
|
CLIENT_SCOPES = None # type: Optional[str]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue