async def _finalize_enrollment(self, context): try: context = await context.finalize() except PkiEnrollmentCertificateNotFoundError: # Nothing to do, the user cancelled the certificate selection prompt return except PkiEnrollmentCertificatePinCodeUnavailableError: # Nothing to do, the user cancelled the pin code prompt return except Exception as exc: show_error(self, _("TEXT_ENROLLMENT_CANNOT_FINALIZE"), exception=exc) return try: await save_device_with_smartcard_in_config( config_dir=self.config.config_dir, device=context.new_device, certificate_id=context.x509_certificate.certificate_id, certificate_sha1=context.x509_certificate.certificate_sha1, ) except Exception as exc: show_error(self, _("TEXT_CANNOT_SAVE_DEVICE"), exception=exc) return await self._remove_enrollment(context) SnackbarManager.inform(_("TEXT_CLAIM_DEVICE_SUCCESSFUL"))
def on_list_error(self, job): status = job.status if status == "offline": return else: errmsg = _("TEXT_USER_LIST_RETRIEVABLE_FAILURE") show_error(self, errmsg, exception=job.exc)
def on_claim_error(self): assert self.claim_user_job assert self.claim_user_job.is_finished() assert self.claim_user_job.status != "ok" status = self.claim_user_job.status if status != "cancelled": if status == "not_found": errmsg = _("TEXT_CLAIM_USER_NOT_FOUND") elif status == "password-mismatch": errmsg = _("TEXT_CLAIM_USER_PASSWORD_MISMATCH") elif status == "password-size": errmsg = _("TEXT_CLAIM_USER_PASSWORD_COMPLEXITY") elif status == "bad-url": errmsg = _("TEXT_CLAIM_USER_INVALID_URL") elif status == "bad-device_name": errmsg = _("TEXT_CLAIM_USER_BAD_DEVICE_NAME") elif status == "bad-user_id": errmsg = _("TEXT_CLAIM_USER_BAD_USER_NAME") elif status == "refused-by-backend": errmsg = _("TEXT_CLAIM_USER_BACKEND_REFUSAL") elif status == "backend-offline": errmsg = _("TEXT_CLAIM_USER_BACKEND_OFFLINE") else: errmsg = _("TEXT_CLAIM_USER_UNKNOWN_FAILURE") show_error(self, errmsg, exception=self.claim_user_job.exc) self.claim_user_job = None self.check_infos()
def go_to_file_link(self, action_addr): for idx in range(self.tab_center.count()): if self.tab_center.tabText(idx) == _("TEXT_TAB_TITLE_LOG_IN_SCREEN"): continue w = self.tab_center.widget(idx) if ( not w or not w.core or w.core.device.organization_addr.organization_id != action_addr.organization_id ): continue user_manifest = w.core.user_fs.get_user_manifest() for wk in user_manifest.workspaces: if not wk.role: continue if wk.id != action_addr.workspace_id: continue central_widget = w.get_central_widget() try: central_widget.show_mount_widget() central_widget.mount_widget.show_files_widget( w.core.user_fs.get_workspace(wk.id), action_addr.path, selected=True ) self.switch_to_tab(idx) except AttributeError: logger.exception("Central widget is not available") return show_error( self, _("TEXT_FILE_LINK_NOT_FOUND_organization").format( organization=action_addr.organization_id ), )
def _on_req_error(self): assert self.req_job assert self.req_job.is_finished() assert self.req_job.status != "ok" status = self.req_job.status if status == "cancelled": return errmsg = None if status == "email_already_exists": errmsg = _("TEXT_ORG_WIZARD_EMAIL_ALREADY_EXISTS") elif status == "organization_already_exists": errmsg = _("TEXT_ORG_WIZARD_ORGANIZATION_ALREADY_EXISTS") elif status == "invalid_email": errmsg = _("TEXT_ORG_WIZARD_INVALID_EMAIL") elif status == "invalid_organization_id": errmsg = _("TEXT_ORG_WIZARD_INVALID_ORGANIZATION_ID") elif status == "invalid_response": errmsg = _("TEXT_ORG_WIZARD_INVALID_RESPONSE") elif status == "offline": errmsg = _("TEXT_ORG_WIZARD_OFFLINE") else: errmsg = _("TEXT_ORG_WIZARD_UNKNOWN_FAILURE") exc = self.req_job.exc if exc.params.get("exc"): exc = exc.params.get("exc") show_error(self, errmsg, exception=exc) self.req_job = None self.button_validate.setEnabled(True) self.button_previous.show()
async def _create_new_device(self, device_label, file_path, passphrase): try: recovery_device = await load_recovery_device(file_path, passphrase) new_device = await generate_new_device_from_recovery( recovery_device, device_label) return new_device except LocalDeviceError as exc: self.button_validate.setEnabled(True) if "Decryption failed" in str(exc): show_error(self, translate("TEXT_IMPORT_KEY_WRONG_PASSPHRASE"), exception=exc) else: show_error(self, translate("IMPORT_KEY_LOCAL_DEVICE_ERROR"), exception=exc) raise JobResultError("error") from exc except BackendNotAvailable as exc: show_error(self, translate("IMPORT_KEY_BACKEND_OFFLINE"), exception=exc) raise JobResultError("backend-error") from exc except BackendConnectionError as exc: show_error(self, translate("IMPORT_KEY_BACKEND_ERROR"), exception=exc) raise JobResultError("backend-error") from exc except Exception as exc: show_error(self, translate("IMPORT_KEY_ERROR"), exception=exc) raise JobResultError("error") from exc
async def prepare_enrollment_request(self): try: self.context = await PkiEnrollmentSubmitterInitialCtx.new(self.addr ) self.widget_user_info.setVisible(True) self.label_cert_error.setVisible(False) self.line_edit_user_name.setText( self.context.x509_certificate.subject_common_name) self.line_edit_user_email.setText( self.context.x509_certificate.subject_email_address) self.line_edit_device.setText(desktop.get_default_device()) self.button_select_cert.setText( str(self.context.x509_certificate.certificate_id)) except PkiEnrollmentCertificateNotFoundError: # User did not provide a certificate (cancelled the prompt). We do nothing. pass except PkiEnrollmentCertificatePinCodeUnavailableError: # User did not provide a pin code (cancelled the prompt). We do nothing. pass except Exception as exc: show_error(self, translate("TEXT_ENROLLMENT_ERROR_LOADING_CERTIFICATE"), exception=exc) self.widget_user_info.setVisible(False) self.label_cert_error.setText( translate("TEXT_ENROLLMENT_ERROR_LOADING_CERTIFICATE")) self.label_cert_error.setVisible(True) self.button_ask_to_join.setEnabled(False)
def _on_claim_device_clicked(self, action_addr=None): if not action_addr: url = get_text_input( parent=self, title=_("TEXT_CLAIM_DEVICE_URL_TITLE"), message=_("TEXT_CLAIM_DEVICE_URL_INSTRUCTIONS"), placeholder=_("TEXT_CLAIM_DEVICE_URL_PLACEHOLDER"), ) if url is None: return elif url == "": show_error(self, _("TEXT_CLAIM_DEVICE_INVALID_URL")) return action_addr = None try: action_addr = BackendOrganizationClaimDeviceAddr.from_url(url) except ValueError as exc: show_error(self, _("TEXT_CLAIM_DEVICE_INVALID_URL"), exception=exc) return ret = ClaimDeviceWidget.exec_modal( jobs_ctx=self.jobs_ctx, config=self.config, addr=action_addr, parent=self ) if ret: self.reload_login_devices()
def _on_claim_clicked(self): # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel` device_label = DeviceLabel( validators.trim_user_name(self.line_edit_device.text())) try: user_name = validators.trim_user_name( self.line_edit_user_full_name.text()) human_handle = HumanHandle(email=self.line_edit_user_email.text(), label=user_name) device_label = DeviceLabel(self.line_edit_device.text()) except ValueError as exc: show_error(self, _("TEXT_CLAIM_USER_INVALID_HUMAN_HANDLE"), exception=exc) return self.button_ok.setDisabled(True) self.widget_info.setDisabled(True) self.label_wait.show() self.claim_job = self.jobs_ctx.submit_job( self.claim_success, self.claim_error, self.claimer.claim_user, device_label=device_label, human_handle=human_handle, )
def _on_create_user_clicked(self): assert not self.create_user_job handle = None # No try/except given `self.line_edit_device` has already been validated against `DeviceLabel` device_label = DeviceLabel( validators.trim_user_name(self.line_edit_device.text())) try: user_name = validators.trim_user_name( self.line_edit_user_full_name.text()) handle = HumanHandle(label=user_name, email=self.line_edit_user_email.text()) except ValueError as exc: show_error(self, _("TEXT_GREET_USER_INVALID_HUMAN_HANDLE"), exception=exc) return self.button_create_user.setDisabled(True) self.button_create_user.setText(_("TEXT_GREET_USER_WAITING")) self.create_user_job = self.jobs_ctx.submit_job( self.create_user_success, self.create_user_error, self.greeter.create_new_user, human_handle=handle, device_label=device_label, profile=self.combo_profile.currentData(), )
def login_with_password(self, key_file, password): message = None exception = None try: device = load_device_with_password(key_file, password) if ParsecApp.is_device_connected( device.organization_addr.organization_id, device.device_id ): message = _("TEXT_LOGIN_ERROR_ALREADY_CONNECTED") else: self.start_core(device) except LocalDeviceError as exc: message = _("TEXT_LOGIN_ERROR_AUTHENTICATION_FAILED") exception = exc except (RuntimeError, MountpointConfigurationError, MountpointDriverCrash) as exc: message = _("TEXT_LOGIN_MOUNTPOINT_ERROR") exception = exc except Exception as exc: message = _("TEXT_LOGIN_UNKNOWN_ERROR") exception = exc logger.exception("Unhandled error during login") finally: if message: show_error(self, message, exception=exception) self.login_failed.emit()
def _on_rename_error(self, job): if job.exc.params.get("multi"): show_error(self, _("TEXT_FILE_RENAME_MULTIPLE_ERROR"), exception=job.exc) else: show_error(self, _("TEXT_FILE_RENAME_ERROR"), exception=job.exc)
def on_get_version_error(self): if self.versions_job and self.versions_job.status != "cancelled": show_error(self, _("TEXT_FILE_HISTORY_LIST_FAILURE"), exception=self.versions_job.exc) self.versions_job = None self.dialog.reject()
async def login_with_smartcard(self, key_file): message = None exception = None try: device = await load_device_with_smartcard(key_file) if ParsecApp.is_device_connected( device.organization_addr.organization_id, device.device_id ): message = _("TEXT_LOGIN_ERROR_ALREADY_CONNECTED") else: self.start_core(device) except LocalDeviceCertificatePinCodeUnavailableError: # User cancelled the prompt self.login_failed.emit() except LocalDeviceError as exc: message = _("TEXT_LOGIN_ERROR_AUTHENTICATION_FAILED") exception = exc except ModuleNotFoundError as exc: message = _("TEXT_LOGIN_SMARTCARD_NOT_AVAILABLE") exception = exc except (RuntimeError, MountpointConfigurationError, MountpointDriverCrash) as exc: message = _("TEXT_LOGIN_MOUNTPOINT_ERROR") exception = exc except Exception as exc: message = _("TEXT_LOGIN_UNKNOWN_ERROR") exception = exc logger.exception("Unhandled error during login") finally: if message: show_error(self, message, exception=exception) self.login_failed.emit()
def goto_file_clicked(self): file_link = get_text_input( self, _("TEXT_WORKSPACE_GOTO_FILE_LINK_TITLE"), _("TEXT_WORKSPACE_GOTO_FILE_LINK_INSTRUCTIONS"), placeholder=_("TEXT_WORKSPACE_GOTO_FILE_LINK_PLACEHOLDER"), default_text="", button_text=_("ACTION_GOTO_FILE_LINK"), ) if not file_link: return url = None try: url = BackendOrganizationFileLinkAddr.from_url(file_link) except ValueError as exc: show_error(self, _("TEXT_WORKSPACE_GOTO_FILE_LINK_INVALID_LINK"), exception=exc) return for widget in self._iter_workspace_buttons(): if widget.workspace_fs.workspace_id == url.workspace_id: self.load_workspace(widget.workspace_fs, path=url.path, selected=True) return show_error(self, _("TEXT_WORKSPACE_GOTO_FILE_LINK_WORKSPACE_NOT_FOUND"))
def add_instance(self, start_arg: Optional[str] = None) -> None: action_addr = None if start_arg: try: action_addr = BackendActionAddr.from_url(start_arg, allow_http_redirection=True) except ValueError as exc: show_error(self, _("TEXT_INVALID_URL"), exception=exc) self.show_top() if not action_addr: self.switch_to_login_tab() elif isinstance(action_addr, BackendOrganizationFileLinkAddr): self.go_to_file_link(action_addr) elif isinstance(action_addr, BackendOrganizationBootstrapAddr): self.show_create_org_widget(action_addr) elif ( isinstance(action_addr, BackendInvitationAddr) and action_addr.invitation_type == InvitationType.USER ): self.show_claim_user_widget(action_addr) elif ( isinstance(action_addr, BackendInvitationAddr) and action_addr.invitation_type == InvitationType.DEVICE ): self.show_claim_device_widget(action_addr) else: show_error(self, _("TEXT_INVALID_URL"))
def _on_import_key(self): key_file, _ = QFileDialog.getOpenFileName( parent=self, caption=translate("ACTION_IMPORT_KEY"), filter=translate("IMPORT_KEY_FILTERS"), initialFilter=translate("IMPORT_KEY_INITIAL_FILTER"), ) if not key_file: return new_device = load_device_file(Path(key_file)) if new_device is None: show_error(self, translate("TEXT_INVALID_DEVICE_KEY")) return rep = ask_question( parent=self, title=translate("ASK_IMPORT_KEY"), message=translate("TEXT_IMPORT_KEY_CONFIRM_organization-user-device").format( organization=new_device.organization_id, user=new_device.short_user_display, device=new_device.device_label, ), button_texts=(translate("ACTION_IMPORT_YES"), translate("ACTION_IMPORT_NO")), ) if rep == translate("ACTION_IMPORT_YES"): key_name = new_device.slughash + ".keys" dest = get_devices_dir(self.config.config_dir).joinpath(key_name) if self._overwrite_key(dest): shutil.copyfile( new_device.key_file_path, os.path.join(get_devices_dir(self.config.config_dir), key_name), ) self.reload_devices() self.key_imported.emit()
def _on_claimer_error(self, job): assert job assert job.is_finished() assert job.status != "ok" # This callback can be called after the creation of a new claimer job in the case # of a restart, due to Qt signals being called later. if job.status == "cancelled": return # Safety net for concurrency issues if self.claimer_job is not job: return self.claimer_job = None msg = "" exc = None if job.status == "invitation-not-found": msg = _("TEXT_CLAIM_USER_INVITATION_NOT_FOUND") elif job.status == "invitation-already-used": msg = _("TEXT_INVITATION_ALREADY_USED") elif job.status == "backend-not-available": msg = _("TEXT_INVITATION_BACKEND_NOT_AVAILABLE") elif job.status == "out-of-ballpark": msg = _("TEXT_BACKEND_STATE_DESYNC") else: msg = _("TEXT_CLAIM_USER_UNKNOWN_ERROR") if job.exc: exc = job.exc.params.get("origin", None) show_error(self, msg, exception=exc) # No point in retrying since the claimer job itself failed, simply close the dialog self.dialog.reject()
def add_instance(self, start_arg: Optional[str] = None): action_addr = None if start_arg: try: action_addr = BackendActionAddr.from_url(start_arg) except ValueError as exc: show_error(self, _("TEXT_INVALID_URL"), exception=exc) idx = self._get_login_tab_index() if idx != -1: self.switch_to_tab(idx) else: tab = self.add_new_tab() tab.show_login_widget() self.on_tab_state_changed(tab, "login") self.switch_to_tab(self.tab_center.count() - 1) idx = self.tab_center.count() - 1 self.show_top() if action_addr and isinstance(action_addr, BackendOrganizationFileLinkAddr): self.go_to_file_link(action_addr) elif action_addr: if isinstance(action_addr, BackendOrganizationBootstrapAddr): self._on_bootstrap_org_clicked(action_addr) elif isinstance(action_addr, BackendOrganizationClaimUserAddr): self._on_claim_user_clicked(action_addr) elif isinstance(action_addr, BackendOrganizationClaimDeviceAddr): self._on_claim_device_clicked(action_addr)
def _on_bootstrap_org_clicked(self, action_addr=None): if not action_addr: url = get_text_input( parent=self, title=_("TEXT_BOOTSTRAP_ORG_URL_TITLE"), message=_("TEXT_BOOTSTRAP_ORG_URL_INSTRUCTIONS"), placeholder=_("TEXT_BOOTSTRAP_ORG_URL_PLACEHOLDER"), validator=validators.BackendOrganizationBootstrapAddrValidator(), ) if url is None: return elif url == "": show_error(self, _("TEXT_BOOTSTRAP_ORG_INVALID_URL")) return action_addr = None try: action_addr = BackendOrganizationBootstrapAddr.from_url(url) except ValueError as exc: show_error(self, _("TEXT_BOOTSTRAP_ORG_INVALID_URL"), exception=exc) return ret = BootstrapOrganizationWidget.exec_modal( jobs_ctx=self.jobs_ctx, config=self.config, addr=action_addr, parent=self ) if ret: self.reload_login_devices() self.try_login(ret[0], ret[1])
def on_registration_error(self): self.line_edit_token.setText("") self.line_edit_url.setText("") self.line_edit_user.setText("") self.widget_registration.hide() self.checkbox_is_admin.show() self.button_register.show() self.line_edit_username.show() if not self.registration_job: return assert self.registration_job.is_finished() status = self.registration_job.status if status == "cancelled": self.registration_job = None return if status == "registration-invite-bad-value": errmsg = _("TEXT_INVITE_USER_BAD_USER_NAME") elif status == "registration-invite-already-exists": errmsg = _("TEXT_INVITE_USER_ALREADY_EXISTS") elif status == "registration-invite-error": errmsg = _("TEXT_INVITE_USER_WRONG_PARAMETERS") elif status == "registration-invite-offline": errmsg = _("TEXT_INVITE_USER_HOST_OFFLINE") elif status == "registration-invite-timeout": errmsg = _("TEXT_INVITE_USER_TIMEOUT") else: errmsg = _("TEXT_INVITE_USER_UNKNOWN_FAILURE") show_error(self, errmsg, exception=self.registration_job.exc) self.registration_job = None
def _on_finalize_clicked(self): password = self.widget_password.password try: save_device_with_password(self.config.config_dir, self.new_device, password) self.succeeded.emit(self.new_device, password) except LocalDeviceAlreadyExistsError as exc: show_error(self, _("TEXT_CLAIM_USER_DEVICE_ALREADY_EXISTS"), exception=exc) self.failed.emit(None)
def open_error_large(self): exc = None try: 1337 / 0 except ZeroDivisionError as e: exc = e custom_dialogs.show_error(self, message=LARGE_TEXT, exception=exc)
def open_error_small(self): exc = None try: 1337 / 0 except ZeroDivisionError as e: exc = e custom_dialogs.show_error(self, message=SMALL_TEXT, exception=exc)
def _on_get_users_error(self, job): assert job.is_finished() assert job.status != "ok" if job.status == "offline": show_error(self, _("TEXT_WORKSPACE_SHARING_OFFLINE")) self.spinner.hide() self.widget_users.show()
def on_mount_error(self, job): if isinstance(job.exc, MountpointError): workspace_id = job.arguments.get("workspace_id") timestamp = job.arguments.get("timestamp") wb = self.get_workspace_button(workspace_id, timestamp) if wb: wb.set_mountpoint_state(False) show_error(self, _("TEXT_WORKSPACE_CANNOT_MOUNT"), exception=job.exc)
def _on_unshare_error(self, job): exc = job.exc show_error( self, _("TEXT_WORKSPACE_SHARING_UNSHARE_ERROR_workspace-user").format( workspace=exc.params.get("workspace_name"), user=exc.params.get("user")), )
def on_rename_error(self, job): if job.status == "invalid-name": show_error(self, _("TEXT_WORKSPACE_RENAME_INVALID_NAME"), exception=job.exc) else: show_error(self, _("TEXT_WORKSPACE_RENAME_UNKNOWN_ERROR"), exception=job.exc)
def _on_delete_error(self, job): if not getattr(job.exc, "params", None): return if job.exc.params.get("multi"): show_error(self, _("TEXT_FILE_DELETE_MULTIPLE_ERROR"), exception=job.exc) else: show_error(self, _("TEXT_FILE_DELETE_ERROR"), exception=job.exc)
def _on_move_error(self, job): exc = job.exc if exc and isinstance(exc.params.get("last_exc", None), FSInvalidArgumentError): show_error(self, _("TEXT_FILE_FOLDER_MOVED_INTO_ITSELF_ERROR")) else: show_error(self, _("TEXT_FILE_PASTE_ERROR")) self.reset()