mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[PM-8252] Use new user-verification for exports on all clients (#9244)
* Move/replace submit and userVerification logic from web into the BaseExportComponent Add "@bitwarden/auth" as dependency to the vault-export-ui package New submit logic also checks for password-encrypted exports which will be need for future UI updates on browser and desktop * Remove import/passing of the unneeded UserVerificationService * Remove app-user-verification from browser and desktop components as the new UI is opened as a self-contained dialog --------- Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com>
This commit is contained in:
parent
e5fb4d80f8
commit
a3d69047c7
@ -29,11 +29,6 @@
|
|||||||
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<app-user-verification ngDefaultControl formControlName="secret" name="Secret">
|
|
||||||
</app-user-verification>
|
|
||||||
</div>
|
|
||||||
<div id="confirmIdentityHelp" class="box-footer">
|
|
||||||
<p>{{ "confirmIdentity" | i18n }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
@ -5,7 +5,6 @@ import { Router } from "@angular/router";
|
|||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -27,7 +26,6 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
policyService: PolicyService,
|
policyService: PolicyService,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
userVerificationService: UserVerificationService,
|
|
||||||
formBuilder: UntypedFormBuilder,
|
formBuilder: UntypedFormBuilder,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
@ -40,7 +38,6 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
eventCollectionService,
|
eventCollectionService,
|
||||||
policyService,
|
policyService,
|
||||||
logService,
|
logService,
|
||||||
userVerificationService,
|
|
||||||
formBuilder,
|
formBuilder,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
|
@ -21,11 +21,6 @@
|
|||||||
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<app-user-verification ngDefaultControl formControlName="secret" name="secret">
|
|
||||||
</app-user-verification>
|
|
||||||
</div>
|
|
||||||
<div id="confirmIdentityHelp" class="box-footer">
|
|
||||||
<p>{{ "confirmIdentity" | i18n }}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,7 +4,6 @@ import { UntypedFormBuilder } from "@angular/forms";
|
|||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -24,7 +23,6 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
|
|||||||
exportService: VaultExportServiceAbstraction,
|
exportService: VaultExportServiceAbstraction,
|
||||||
eventCollectionService: EventCollectionService,
|
eventCollectionService: EventCollectionService,
|
||||||
policyService: PolicyService,
|
policyService: PolicyService,
|
||||||
userVerificationService: UserVerificationService,
|
|
||||||
formBuilder: UntypedFormBuilder,
|
formBuilder: UntypedFormBuilder,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
@ -38,7 +36,6 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
|
|||||||
eventCollectionService,
|
eventCollectionService,
|
||||||
policyService,
|
policyService,
|
||||||
logService,
|
logService,
|
||||||
userVerificationService,
|
|
||||||
formBuilder,
|
formBuilder,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
|
@ -5,7 +5,6 @@ import { ActivatedRoute } from "@angular/router";
|
|||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -30,7 +29,6 @@ export class OrganizationVaultExportComponent extends ExportComponent {
|
|||||||
private route: ActivatedRoute,
|
private route: ActivatedRoute,
|
||||||
policyService: PolicyService,
|
policyService: PolicyService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
userVerificationService: UserVerificationService,
|
|
||||||
formBuilder: UntypedFormBuilder,
|
formBuilder: UntypedFormBuilder,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
@ -43,7 +41,6 @@ export class OrganizationVaultExportComponent extends ExportComponent {
|
|||||||
eventCollectionService,
|
eventCollectionService,
|
||||||
policyService,
|
policyService,
|
||||||
logService,
|
logService,
|
||||||
userVerificationService,
|
|
||||||
formBuilder,
|
formBuilder,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { UntypedFormBuilder } from "@angular/forms";
|
import { UntypedFormBuilder } from "@angular/forms";
|
||||||
|
|
||||||
import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
|
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||||
@ -26,7 +24,6 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
eventCollectionService: EventCollectionService,
|
eventCollectionService: EventCollectionService,
|
||||||
policyService: PolicyService,
|
policyService: PolicyService,
|
||||||
logService: LogService,
|
logService: LogService,
|
||||||
userVerificationService: UserVerificationService,
|
|
||||||
formBuilder: UntypedFormBuilder,
|
formBuilder: UntypedFormBuilder,
|
||||||
fileDownloadService: FileDownloadService,
|
fileDownloadService: FileDownloadService,
|
||||||
dialogService: DialogService,
|
dialogService: DialogService,
|
||||||
@ -39,84 +36,10 @@ export class ExportComponent extends BaseExportComponent {
|
|||||||
eventCollectionService,
|
eventCollectionService,
|
||||||
policyService,
|
policyService,
|
||||||
logService,
|
logService,
|
||||||
userVerificationService,
|
|
||||||
formBuilder,
|
formBuilder,
|
||||||
fileDownloadService,
|
fileDownloadService,
|
||||||
dialogService,
|
dialogService,
|
||||||
organizationService,
|
organizationService,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
submit = async () => {
|
|
||||||
if (this.isFileEncryptedExport && this.filePassword != this.confirmFilePassword) {
|
|
||||||
this.platformUtilsService.showToast(
|
|
||||||
"error",
|
|
||||||
this.i18nService.t("errorOccurred"),
|
|
||||||
this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch"),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.exportForm.markAllAsTouched();
|
|
||||||
if (this.exportForm.invalid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.disabledByPolicy) {
|
|
||||||
this.platformUtilsService.showToast(
|
|
||||||
"error",
|
|
||||||
null,
|
|
||||||
this.i18nService.t("personalVaultExportPolicyInEffect"),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userVerified = await this.verifyUser();
|
|
||||||
if (!userVerified) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
this.doExport();
|
|
||||||
};
|
|
||||||
|
|
||||||
protected saved() {
|
|
||||||
super.saved();
|
|
||||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("exportSuccess"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async verifyUser(): Promise<boolean> {
|
|
||||||
let confirmDescription = "exportWarningDesc";
|
|
||||||
if (this.isFileEncryptedExport) {
|
|
||||||
confirmDescription = "fileEncryptedExportWarningDesc";
|
|
||||||
} else if (this.isAccountEncryptedExport) {
|
|
||||||
confirmDescription = "encExportKeyWarningDesc";
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await UserVerificationDialogComponent.open(this.dialogService, {
|
|
||||||
title: "confirmVaultExport",
|
|
||||||
bodyText: confirmDescription,
|
|
||||||
confirmButtonOptions: {
|
|
||||||
text: "exportVault",
|
|
||||||
type: "primary",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle the result of the dialog based on user action and verification success
|
|
||||||
if (result.userAction === "cancel") {
|
|
||||||
// User cancelled the dialog
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// User confirmed the dialog so check verification success
|
|
||||||
if (!result.verificationSuccess) {
|
|
||||||
if (result.noAvailableClientVerificationMethods) {
|
|
||||||
// No client-side verification methods are available
|
|
||||||
// Could send user to configure a verification method like PIN or biometrics
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@bitwarden/common": "file:../../../../common",
|
"@bitwarden/common": "file:../../../../common",
|
||||||
"@bitwarden/angular": "file:../../../../angular",
|
"@bitwarden/angular": "file:../../../../angular",
|
||||||
|
"@bitwarden/auth": "file:../../../../auth",
|
||||||
"@bitwarden/vault-export-core": "file:../vault-export-core"
|
"@bitwarden/vault-export-core": "file:../vault-export-core"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,12 @@ import { UntypedFormBuilder, Validators } from "@angular/forms";
|
|||||||
import { map, merge, Observable, startWith, Subject, takeUntil } from "rxjs";
|
import { map, merge, Observable, startWith, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { PasswordStrengthComponent } from "@bitwarden/angular/tools/password-strength/password-strength.component";
|
import { PasswordStrengthComponent } from "@bitwarden/angular/tools/password-strength/password-strength.component";
|
||||||
|
import { UserVerificationDialogComponent } from "@bitwarden/auth/angular";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
import { PolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
|
||||||
import { EventType } from "@bitwarden/common/enums";
|
import { EventType } from "@bitwarden/common/enums";
|
||||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||||
@ -67,7 +67,6 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
protected eventCollectionService: EventCollectionService,
|
protected eventCollectionService: EventCollectionService,
|
||||||
private policyService: PolicyService,
|
private policyService: PolicyService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
private userVerificationService: UserVerificationService,
|
|
||||||
private formBuilder: UntypedFormBuilder,
|
private formBuilder: UntypedFormBuilder,
|
||||||
protected fileDownloadService: FileDownloadService,
|
protected fileDownloadService: FileDownloadService,
|
||||||
protected dialogService: DialogService,
|
protected dialogService: DialogService,
|
||||||
@ -154,7 +153,21 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
submit = async () => {
|
||||||
|
if (this.isFileEncryptedExport && this.filePassword != this.confirmFilePassword) {
|
||||||
|
this.platformUtilsService.showToast(
|
||||||
|
"error",
|
||||||
|
this.i18nService.t("errorOccurred"),
|
||||||
|
this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch"),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exportForm.markAllAsTouched();
|
||||||
|
if (this.exportForm.invalid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.disabledByPolicy) {
|
if (this.disabledByPolicy) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
@ -164,49 +177,52 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const acceptedWarning = await this.warningDialog();
|
const userVerified = await this.verifyUser();
|
||||||
if (!acceptedWarning) {
|
if (!userVerified) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
const secret = this.exportForm.get("secret").value;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await this.userVerificationService.verifyUser(secret);
|
|
||||||
} catch (e) {
|
|
||||||
this.platformUtilsService.showToast("error", this.i18nService.t("errorOccurred"), e.message);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
await this.doExport();
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
};
|
||||||
this.doExport();
|
|
||||||
}
|
|
||||||
|
|
||||||
async warningDialog() {
|
|
||||||
if (this.encryptedFormat) {
|
|
||||||
return await this.dialogService.openSimpleDialog({
|
|
||||||
title: { key: "confirmVaultExport" },
|
|
||||||
content:
|
|
||||||
this.i18nService.t("encExportKeyWarningDesc") +
|
|
||||||
" " +
|
|
||||||
this.i18nService.t("encExportAccountWarningDesc"),
|
|
||||||
acceptButtonText: { key: "exportVault" },
|
|
||||||
type: "warning",
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return await this.dialogService.openSimpleDialog({
|
|
||||||
title: { key: "confirmVaultExport" },
|
|
||||||
content: { key: "exportWarningDesc" },
|
|
||||||
acceptButtonText: { key: "exportVault" },
|
|
||||||
type: "warning",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected saved() {
|
protected saved() {
|
||||||
this.onSaved.emit();
|
this.onSaved.emit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async verifyUser(): Promise<boolean> {
|
||||||
|
let confirmDescription = "exportWarningDesc";
|
||||||
|
if (this.isFileEncryptedExport) {
|
||||||
|
confirmDescription = "fileEncryptedExportWarningDesc";
|
||||||
|
} else if (this.isAccountEncryptedExport) {
|
||||||
|
confirmDescription = "encExportKeyWarningDesc";
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await UserVerificationDialogComponent.open(this.dialogService, {
|
||||||
|
title: "confirmVaultExport",
|
||||||
|
bodyText: confirmDescription,
|
||||||
|
confirmButtonOptions: {
|
||||||
|
text: "exportVault",
|
||||||
|
type: "primary",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle the result of the dialog based on user action and verification success
|
||||||
|
if (result.userAction === "cancel") {
|
||||||
|
// User cancelled the dialog
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// User confirmed the dialog so check verification success
|
||||||
|
if (!result.verificationSuccess) {
|
||||||
|
if (result.noAvailableClientVerificationMethods) {
|
||||||
|
// No client-side verification methods are available
|
||||||
|
// Could send user to configure a verification method like PIN or biometrics
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected async getExportData(): Promise<string> {
|
protected async getExportData(): Promise<string> {
|
||||||
return Utils.isNullOrWhitespace(this.organizationId)
|
return Utils.isNullOrWhitespace(this.organizationId)
|
||||||
? this.exportService.getExport(this.format, this.filePassword)
|
? this.exportService.getExport(this.format, this.filePassword)
|
||||||
|
Loading…
Reference in New Issue
Block a user