Account.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # Copyright (c) 2018 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from typing import Optional, Dict, TYPE_CHECKING
  4. from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot, pyqtProperty
  5. from UM.i18n import i18nCatalog
  6. from UM.Message import Message
  7. from cura.OAuth2.AuthorizationService import AuthorizationService
  8. from cura.OAuth2.Models import OAuth2Settings
  9. if TYPE_CHECKING:
  10. from cura.CuraApplication import CuraApplication
  11. i18n_catalog = i18nCatalog("cura")
  12. ## The account API provides a version-proof bridge to use Ultimaker Accounts
  13. #
  14. # Usage:
  15. # ``from cura.API import CuraAPI
  16. # api = CuraAPI()
  17. # api.account.login()
  18. # api.account.logout()
  19. # api.account.userProfile # Who is logged in``
  20. #
  21. class Account(QObject):
  22. # Signal emitted when user logged in or out.
  23. loginStateChanged = pyqtSignal(bool)
  24. def __init__(self, application: "CuraApplication", parent = None) -> None:
  25. super().__init__(parent)
  26. self._application = application
  27. self._error_message = None # type: Optional[Message]
  28. self._logged_in = False
  29. self._callback_port = 32118
  30. self._oauth_root = "https://account.ultimaker.com"
  31. self._cloud_api_root = "https://api.ultimaker.com"
  32. self._oauth_settings = OAuth2Settings(
  33. OAUTH_SERVER_URL= self._oauth_root,
  34. CALLBACK_PORT=self._callback_port,
  35. CALLBACK_URL="http://localhost:{}/callback".format(self._callback_port),
  36. CLIENT_ID="um---------------ultimaker_cura_drive_plugin",
  37. CLIENT_SCOPES="account.user.read drive.backup.read drive.backup.write packages.download packages.rating.read packages.rating.write",
  38. AUTH_DATA_PREFERENCE_KEY="general/ultimaker_auth_data",
  39. AUTH_SUCCESS_REDIRECT="{}/app/auth-success".format(self._oauth_root),
  40. AUTH_FAILED_REDIRECT="{}/app/auth-error".format(self._oauth_root)
  41. )
  42. self._authorization_service = AuthorizationService(self._oauth_settings)
  43. def initialize(self) -> None:
  44. self._authorization_service.initialize(self._application.getPreferences())
  45. self._authorization_service.onAuthStateChanged.connect(self._onLoginStateChanged)
  46. self._authorization_service.onAuthenticationError.connect(self._onLoginStateChanged)
  47. self._authorization_service.loadAuthDataFromPreferences()
  48. @pyqtProperty(bool, notify=loginStateChanged)
  49. def isLoggedIn(self) -> bool:
  50. return self._logged_in
  51. def _onLoginStateChanged(self, logged_in: bool = False, error_message: Optional[str] = None) -> None:
  52. if error_message:
  53. if self._error_message:
  54. self._error_message.hide()
  55. self._error_message = Message(error_message, title = i18n_catalog.i18nc("@info:title", "Login failed"))
  56. self._error_message.show()
  57. if self._logged_in != logged_in:
  58. self._logged_in = logged_in
  59. self.loginStateChanged.emit(logged_in)
  60. @pyqtSlot()
  61. def login(self) -> None:
  62. if self._logged_in:
  63. # Nothing to do, user already logged in.
  64. return
  65. self._authorization_service.startAuthorizationFlow()
  66. @pyqtProperty(str, notify=loginStateChanged)
  67. def userName(self):
  68. user_profile = self._authorization_service.getUserProfile()
  69. if not user_profile:
  70. return None
  71. return user_profile.username
  72. @pyqtProperty(str, notify = loginStateChanged)
  73. def profileImageUrl(self):
  74. user_profile = self._authorization_service.getUserProfile()
  75. if not user_profile:
  76. return None
  77. return user_profile.profile_image_url
  78. @pyqtProperty(str, notify=loginStateChanged)
  79. def accessToken(self) -> Optional[str]:
  80. return self._authorization_service.getAccessToken()
  81. # Get the profile of the logged in user
  82. # @returns None if no user is logged in, a dict containing user_id, username and profile_image_url
  83. @pyqtProperty("QVariantMap", notify = loginStateChanged)
  84. def userProfile(self) -> Optional[Dict[str, Optional[str]]]:
  85. user_profile = self._authorization_service.getUserProfile()
  86. if not user_profile:
  87. return None
  88. return user_profile.__dict__
  89. @pyqtSlot()
  90. def logout(self) -> None:
  91. if not self._logged_in:
  92. return # Nothing to do, user isn't logged in.
  93. self._authorization_service.deleteAuthData()