mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-08-09 06:45:09 -06:00
Merge branch 'CURA-8138_check_user_access_DF' of github.com:Ultimaker/Cura
This commit is contained in:
commit
5aa4a6f713
5 changed files with 85 additions and 6 deletions
|
@ -22,6 +22,7 @@ from .DFFileUploader import DFFileUploader
|
|||
from .DFLibraryFileUploadRequest import DFLibraryFileUploadRequest
|
||||
from .DFLibraryFileUploadResponse import DFLibraryFileUploadResponse
|
||||
from .DFPrintJobUploadRequest import DFPrintJobUploadRequest
|
||||
from .DigitalFactoryFeatureBudgetResponse import DigitalFactoryFeatureBudgetResponse
|
||||
from .DigitalFactoryFileResponse import DigitalFactoryFileResponse
|
||||
from .DigitalFactoryProjectResponse import DigitalFactoryProjectResponse
|
||||
from .PaginationLinks import PaginationLinks
|
||||
|
@ -57,6 +58,27 @@ class DigitalFactoryApiClient:
|
|||
|
||||
self._projects_pagination_mgr = PaginationManager(limit = projects_limit_per_page) if projects_limit_per_page else None # type: Optional[PaginationManager]
|
||||
|
||||
def checkUserHasAccess(self, callback: Callable) -> None:
|
||||
"""Checks if the user has any sort of access to the digital library.
|
||||
A user is considered to have access if the max-# of private projects is greater then 0 (or -1 for unlimited).
|
||||
"""
|
||||
|
||||
def callbackWrap(response: Optional[Any] = None, *args, **kwargs) -> None:
|
||||
if (response is not None and isinstance(response, DigitalFactoryFeatureBudgetResponse) and
|
||||
response.library_max_private_projects is not None):
|
||||
callback(
|
||||
response.library_max_private_projects == -1 or # Note: -1 is unlimited
|
||||
response.library_max_private_projects > 0)
|
||||
else:
|
||||
Logger.warning(f"Digital Factory: Response is not a feature budget, likely an error: {str(response)}")
|
||||
callback(False)
|
||||
|
||||
self._http.get(f"{self.CURA_API_ROOT}/feature_budgets",
|
||||
scope = self._scope,
|
||||
callback = self._parseCallback(callbackWrap, DigitalFactoryFeatureBudgetResponse, callbackWrap),
|
||||
error_callback = callbackWrap,
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def getProject(self, library_project_id: str, on_finished: Callable[[DigitalFactoryProjectResponse], Any], failed: Callable) -> None:
|
||||
"""
|
||||
Retrieves a digital factory project by its library project id.
|
||||
|
|
|
@ -89,6 +89,9 @@ class DigitalFactoryController(QObject):
|
|||
uploadFileError = Signal()
|
||||
uploadFileFinished = Signal()
|
||||
|
||||
"""Signal to inform about the state of user access."""
|
||||
userAccessStateChanged = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, application: CuraApplication) -> None:
|
||||
super().__init__(parent = None)
|
||||
|
||||
|
@ -106,6 +109,7 @@ class DigitalFactoryController(QObject):
|
|||
self._has_more_projects_to_load = False
|
||||
|
||||
self._account = self._application.getInstance().getCuraAPI().account # type: Account
|
||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||
self._current_workspace_information = CuraApplication.getInstance().getCurrentWorkspaceInformation()
|
||||
|
||||
# Initialize the project model
|
||||
|
@ -131,6 +135,8 @@ class DigitalFactoryController(QObject):
|
|||
self._application.engineCreatedSignal.connect(self._onEngineCreated)
|
||||
self._application.initializationFinished.connect(self._applicationInitializationFinished)
|
||||
|
||||
self._user_has_access = False
|
||||
|
||||
def clear(self) -> None:
|
||||
self._project_model.clearProjects()
|
||||
self._api.clear()
|
||||
|
@ -143,16 +149,24 @@ class DigitalFactoryController(QObject):
|
|||
|
||||
self.setSelectedProjectIndex(-1)
|
||||
|
||||
def _onLoginStateChanged(self, logged_in: bool) -> None:
|
||||
def callback(has_access, **kwargs):
|
||||
self._user_has_access = has_access
|
||||
self.userAccessStateChanged.emit(logged_in)
|
||||
|
||||
self._api.checkUserHasAccess(callback)
|
||||
|
||||
def userAccountHasLibraryAccess(self) -> bool:
|
||||
"""
|
||||
Checks whether the currently logged in user account has access to the Digital Library
|
||||
|
||||
:return: True if the user account has Digital Library access, else False
|
||||
"""
|
||||
subscriptions = [] # type: List[Dict[str, Any]]
|
||||
if self._account.userProfile:
|
||||
subscriptions = self._account.userProfile.get("subscriptions", [])
|
||||
return len(subscriptions) > 0
|
||||
if len(subscriptions) > 0:
|
||||
return True
|
||||
return self._user_has_access
|
||||
|
||||
def initialize(self, preselected_project_id: Optional[str] = None) -> None:
|
||||
self.clear()
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# Copyright (c) 2021 Ultimaker B.V.
|
||||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
from .BaseModel import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class DigitalFactoryFeatureBudgetResponse(BaseModel):
|
||||
"""Class representing the capabilities of a user account for Digital Library.
|
||||
NOTE: For each max_..._projects fields, '-1' means unlimited!
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
library_can_use_business_value: Optional[bool] = False,
|
||||
library_can_use_comments: Optional[bool] = False,
|
||||
library_can_use_status: Optional[bool] = False,
|
||||
library_can_use_tags: Optional[bool] = False,
|
||||
library_can_use_technical_requirements: Optional[bool] = False,
|
||||
library_max_organization_shared_projects: Optional[int] = False, # -1 means unlimited
|
||||
library_max_private_projects: Optional[int] = False, # -1 means unlimited
|
||||
library_max_team_shared_projects: Optional[int] = False, # -1 means unlimited
|
||||
**kwargs) -> None:
|
||||
|
||||
self.library_can_use_business_value = library_can_use_business_value
|
||||
self.library_can_use_comments = library_can_use_comments
|
||||
self.library_can_use_status = library_can_use_status
|
||||
self.library_can_use_tags = library_can_use_tags
|
||||
self.library_can_use_technical_requirements = library_can_use_technical_requirements
|
||||
self.library_max_organization_shared_projects = library_max_organization_shared_projects # -1 means unlimited
|
||||
self.library_max_private_projects = library_max_private_projects # -1 means unlimited
|
||||
self.library_max_team_shared_projects = library_max_team_shared_projects # -1 means unlimited
|
||||
super().__init__(**kwargs)
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "max private: {}, max org: {}, max team: {}".format(
|
||||
self.library_max_private_projects,
|
||||
self.library_max_organization_shared_projects,
|
||||
self.library_max_team_shared_projects)
|
||||
|
||||
# Validates the model, raising an exception if the model is invalid.
|
||||
def validate(self) -> None:
|
||||
super().validate()
|
||||
# No validation for now, as the response can be "data: []", which should be interpreted as all False and 0's
|
|
@ -22,7 +22,7 @@ class DigitalFactoryFileProvider(FileProvider):
|
|||
self._dialog = None
|
||||
|
||||
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
|
||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||
self._controller.userAccessStateChanged.connect(self._onUserAccessStateChanged)
|
||||
self.enabled = self._account.isLoggedIn and self._controller.userAccountHasLibraryAccess()
|
||||
self.priority = 10
|
||||
|
||||
|
@ -53,7 +53,7 @@ class DigitalFactoryFileProvider(FileProvider):
|
|||
if not self._dialog:
|
||||
Logger.log("e", "Unable to create the Digital Library Open dialog.")
|
||||
|
||||
def _onLoginStateChanged(self, logged_in: bool) -> None:
|
||||
def _onUserAccessStateChanged(self, logged_in: bool) -> None:
|
||||
"""
|
||||
Sets the enabled status of the DigitalFactoryFileProvider according to the account's login status
|
||||
:param logged_in: The new login status
|
||||
|
|
|
@ -45,7 +45,7 @@ class DigitalFactoryOutputDevice(ProjectOutputDevice):
|
|||
self._writing = False
|
||||
|
||||
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
|
||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||
self._controller.userAccessStateChanged.connect(self._onUserAccessStateChanged)
|
||||
self.enabled = self._account.isLoggedIn and self._controller.userAccountHasLibraryAccess()
|
||||
|
||||
self._current_workspace_information = CuraApplication.getInstance().getCurrentWorkspaceInformation()
|
||||
|
@ -97,7 +97,7 @@ class DigitalFactoryOutputDevice(ProjectOutputDevice):
|
|||
if not self._dialog:
|
||||
Logger.log("e", "Unable to create the Digital Library Save dialog.")
|
||||
|
||||
def _onLoginStateChanged(self, logged_in: bool) -> None:
|
||||
def _onUserAccessStateChanged(self, logged_in: bool) -> None:
|
||||
"""
|
||||
Sets the enabled status of the DigitalFactoryOutputDevice according to the account's login status
|
||||
:param logged_in: The new login status
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue