mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
[AC-1104] Fix access import/export with custom permission (#5014)
* [AC-1104] Allow importBlockedByPolicy to be overridden Adjust the import component so that the importBlockedByPolicy flag can be overridden by the org import component to always return false. * [AC-1104] Allow disabledByPolicy to be overridden in export component Adjust the export component so that the disabledByPolicy flag can be overridden by the org export component to always return false. * [AC-1104] Cleanup logic that disables export form * [AC-1104] Use observable subscription for assigning importBlockedByPolicy flag * [AC-1264] Add optional success callback for import component Use the optional callback in org-import.component.ts to clear the file and file contents when the user does not have access to the vault page * [AC-1264] Re-order properties * [AC-1104] Refactor import component to only use onSuccess callback that can be overridden
This commit is contained in:
parent
2f44b9b0dd
commit
e092d42b72
@ -54,6 +54,10 @@ export class OrganizationExportComponent extends ExportComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected get disabledByPolicy(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
this.route.parent.parent.params.subscribe(async (params) => {
|
||||||
@ -62,10 +66,6 @@ export class OrganizationExportComponent extends ExportComponent {
|
|||||||
await super.ngOnInit();
|
await super.ngOnInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkExportDisabled() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getExportData() {
|
getExportData() {
|
||||||
if (this.isFileEncryptedExport) {
|
if (this.isFileEncryptedExport) {
|
||||||
return this.exportService.getPasswordProtectedExport(this.filePassword, this.organizationId);
|
return this.exportService.getPasswordProtectedExport(this.filePassword, this.organizationId);
|
||||||
|
@ -1,13 +1,18 @@
|
|||||||
import { Component } from "@angular/core";
|
import { Component } from "@angular/core";
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import { switchMap, takeUntil } from "rxjs/operators";
|
||||||
|
|
||||||
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
|
||||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
import {
|
||||||
|
canAccessVaultTab,
|
||||||
|
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { ImportServiceAbstraction } from "@bitwarden/importer";
|
import { ImportServiceAbstraction } from "@bitwarden/importer";
|
||||||
|
|
||||||
@ -19,7 +24,11 @@ import { ImportComponent } from "../../../../tools/import-export/import.componen
|
|||||||
})
|
})
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||||
export class OrganizationImportComponent extends ImportComponent {
|
export class OrganizationImportComponent extends ImportComponent {
|
||||||
organizationName: string;
|
organization: Organization;
|
||||||
|
|
||||||
|
protected get importBlockedByPolicy(): boolean {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
i18nService: I18nService,
|
i18nService: I18nService,
|
||||||
@ -47,21 +56,32 @@ export class OrganizationImportComponent extends ImportComponent {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
ngOnInit() {
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
this.route.params
|
||||||
this.route.parent.parent.params.subscribe(async (params) => {
|
.pipe(
|
||||||
this.organizationId = params.organizationId;
|
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
||||||
this.successNavigate = ["organizations", this.organizationId, "vault"];
|
takeUntil(this.destroy$)
|
||||||
await super.ngOnInit();
|
)
|
||||||
});
|
.subscribe((organization) => {
|
||||||
const organization = await this.organizationService.get(this.organizationId);
|
this.organizationId = organization.id;
|
||||||
this.organizationName = organization.name;
|
this.organization = organization;
|
||||||
|
});
|
||||||
|
super.ngOnInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async onSuccessfulImport(): Promise<void> {
|
||||||
|
if (canAccessVaultTab(this.organization)) {
|
||||||
|
await this.router.navigate(["organizations", this.organizationId, "vault"]);
|
||||||
|
} else {
|
||||||
|
this.fileSelected = null;
|
||||||
|
this.fileContents = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
const confirmed = await this.dialogService.openSimpleDialog({
|
const confirmed = await this.dialogService.openSimpleDialog({
|
||||||
title: { key: "warning" },
|
title: { key: "warning" },
|
||||||
content: { key: "importWarning", placeholders: [this.organizationName] },
|
content: { key: "importWarning", placeholders: [this.organization.name] },
|
||||||
type: SimpleDialogType.WARNING,
|
type: SimpleDialogType.WARNING,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||||
import { Router } from "@angular/router";
|
import { Router } from "@angular/router";
|
||||||
import * as JSZip from "jszip";
|
import * as JSZip from "jszip";
|
||||||
import { firstValueFrom } from "rxjs";
|
import { Subject } from "rxjs";
|
||||||
|
import { takeUntil } from "rxjs/operators";
|
||||||
import Swal, { SweetAlertIcon } from "sweetalert2";
|
import Swal, { SweetAlertIcon } from "sweetalert2";
|
||||||
|
|
||||||
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
|
||||||
@ -14,28 +15,29 @@ import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
|||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import {
|
import {
|
||||||
ImportOption,
|
ImportOption,
|
||||||
ImportType,
|
|
||||||
ImportResult,
|
ImportResult,
|
||||||
ImportServiceAbstraction,
|
ImportServiceAbstraction,
|
||||||
|
ImportType,
|
||||||
} from "@bitwarden/importer";
|
} from "@bitwarden/importer";
|
||||||
|
|
||||||
import { ImportSuccessDialogComponent, FilePasswordPromptComponent } from "./dialog";
|
import { FilePasswordPromptComponent, ImportSuccessDialogComponent } from "./dialog";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-import",
|
selector: "app-import",
|
||||||
templateUrl: "import.component.html",
|
templateUrl: "import.component.html",
|
||||||
})
|
})
|
||||||
export class ImportComponent implements OnInit {
|
export class ImportComponent implements OnInit, OnDestroy {
|
||||||
featuredImportOptions: ImportOption[];
|
featuredImportOptions: ImportOption[];
|
||||||
importOptions: ImportOption[];
|
importOptions: ImportOption[];
|
||||||
format: ImportType = null;
|
format: ImportType = null;
|
||||||
fileContents: string;
|
fileContents: string;
|
||||||
fileSelected: File;
|
fileSelected: File;
|
||||||
loading = false;
|
loading = false;
|
||||||
importBlockedByPolicy = false;
|
|
||||||
|
|
||||||
protected organizationId: string = null;
|
protected organizationId: string = null;
|
||||||
protected successNavigate: any[] = ["vault"];
|
protected destroy$ = new Subject<void>();
|
||||||
|
|
||||||
|
private _importBlockedByPolicy = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
@ -49,12 +51,26 @@ export class ImportComponent implements OnInit {
|
|||||||
protected dialogService: DialogServiceAbstraction
|
protected dialogService: DialogServiceAbstraction
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async ngOnInit() {
|
protected get importBlockedByPolicy(): boolean {
|
||||||
|
return this._importBlockedByPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that is called after a successful import.
|
||||||
|
*/
|
||||||
|
protected async onSuccessfulImport(): Promise<void> {
|
||||||
|
await this.router.navigate(["vault"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.setImportOptions();
|
this.setImportOptions();
|
||||||
|
|
||||||
this.importBlockedByPolicy = await firstValueFrom(
|
this.policyService
|
||||||
this.policyService.policyAppliesToActiveUser$(PolicyType.PersonalOwnership)
|
.policyAppliesToActiveUser$(PolicyType.PersonalOwnership)
|
||||||
);
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((policyAppliesToActiveUser) => {
|
||||||
|
this._importBlockedByPolicy = policyAppliesToActiveUser;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
@ -134,7 +150,7 @@ export class ImportComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.syncService.fullSync(true);
|
this.syncService.fullSync(true);
|
||||||
this.router.navigate(this.successNavigate);
|
await this.onSuccessfulImport();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.error(e);
|
this.error(e);
|
||||||
this.logService.error(e);
|
this.logService.error(e);
|
||||||
@ -264,4 +280,9 @@ export class ImportComponent implements OnInit {
|
|||||||
|
|
||||||
return await ref.onClosedPromise();
|
return await ref.onClosedPromise();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.destroy$.next();
|
||||||
|
this.destroy$.complete();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Directive, EventEmitter, OnDestroy, OnInit, Output } from "@angular/core";
|
import { Directive, EventEmitter, OnDestroy, OnInit, Output } from "@angular/core";
|
||||||
import { UntypedFormBuilder, Validators } from "@angular/forms";
|
import { UntypedFormBuilder, Validators } from "@angular/forms";
|
||||||
import { merge, takeUntil, Subject, startWith } from "rxjs";
|
import { merge, startWith, Subject, takeUntil } from "rxjs";
|
||||||
|
|
||||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||||
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
import { EventCollectionService } from "@bitwarden/common/abstractions/event/event-collection.service";
|
||||||
@ -21,7 +21,11 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
@Output() onSaved = new EventEmitter();
|
@Output() onSaved = new EventEmitter();
|
||||||
|
|
||||||
formPromise: Promise<string>;
|
formPromise: Promise<string>;
|
||||||
disabledByPolicy = false;
|
private _disabledByPolicy = false;
|
||||||
|
|
||||||
|
protected get disabledByPolicy(): boolean {
|
||||||
|
return this._disabledByPolicy;
|
||||||
|
}
|
||||||
|
|
||||||
exportForm = this.formBuilder.group({
|
exportForm = this.formBuilder.group({
|
||||||
format: ["json"],
|
format: ["json"],
|
||||||
@ -59,11 +63,12 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
.policyAppliesToActiveUser$(PolicyType.DisablePersonalVaultExport)
|
.policyAppliesToActiveUser$(PolicyType.DisablePersonalVaultExport)
|
||||||
.pipe(takeUntil(this.destroy$))
|
.pipe(takeUntil(this.destroy$))
|
||||||
.subscribe((policyAppliesToActiveUser) => {
|
.subscribe((policyAppliesToActiveUser) => {
|
||||||
this.disabledByPolicy = policyAppliesToActiveUser;
|
this._disabledByPolicy = policyAppliesToActiveUser;
|
||||||
|
if (this.disabledByPolicy) {
|
||||||
|
this.exportForm.disable();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.checkExportDisabled();
|
|
||||||
|
|
||||||
merge(
|
merge(
|
||||||
this.exportForm.get("format").valueChanges,
|
this.exportForm.get("format").valueChanges,
|
||||||
this.exportForm.get("fileEncryptionType").valueChanges
|
this.exportForm.get("fileEncryptionType").valueChanges
|
||||||
@ -77,12 +82,6 @@ export class ExportComponent implements OnInit, OnDestroy {
|
|||||||
this.destroy$.next();
|
this.destroy$.next();
|
||||||
}
|
}
|
||||||
|
|
||||||
async checkExportDisabled() {
|
|
||||||
if (this.disabledByPolicy) {
|
|
||||||
this.exportForm.disable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get encryptedFormat() {
|
get encryptedFormat() {
|
||||||
return this.format === "encrypted_json";
|
return this.format === "encrypted_json";
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user