mirror of
https://github.com/bitwarden/browser.git
synced 2024-11-24 12:06:15 +01:00
[PM-4222] Make importer UI reusable (#6504)
* Split up import/export into separate modules * Fix routing and apply PR feedback * Renamed OrganizationExport exports to OrganizationVaultExport * Make import dialogs standalone and move them to libs/importer * Make import.component re-usable - Move functionality which was previously present on the org-import.component into import.component - Move import.component into libs/importer Make import.component standalone Create import-web.component to represent Web UI Fix module imports and routing Remove unused org-import-files * Renamed filenames according to export rename * Make ImportWebComponent standalone, simplify routing * Pass organizationId as Input to ImportComponent * use formLoading and formDisabled outputs * Emit an event when the import succeeds Remove Angular router from base-component as other clients might not have routing (i.e. desktop) Move logic that happened on web successful import into the import-web.component * fix table themes on desktop & browser * fix fileSelector button styles * update selectors to use tools prefix; remove unused selectors * Wall off UI components in libs/importer Create barrel-file for libs/importer/components Remove components and dialog exports from libs/importer/index.ts Extend libs/shared/tsconfig.libs.json to include @bitwarden/importer/ui -> libs/importer/components Extend apps/web/tsconfig.ts to include @bitwarden/importer/ui Update all usages * Rename @bitwarden/importer to @bitwarden/importer/core Create more barrel files in libs/importer/* Update imports within libs/importer Extend tsconfig files Update imports in web, desktop, browser and cli * Lazy-load the ImportWebComponent via both routes * Use SharedModule as import in import-web.component * File selector should be displayed as secondary * Use bitSubmit to override submit preventDefault (#6607) Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com> --------- Co-authored-by: Daniel James Smith <djsmith85@users.noreply.github.com> Co-authored-by: William Martin <contact@willmartian.com>
This commit is contained in:
parent
d0e72f5554
commit
9e290a3fed
@ -113,7 +113,7 @@ import {
|
|||||||
ImportApiService,
|
ImportApiService,
|
||||||
ImportServiceAbstraction,
|
ImportServiceAbstraction,
|
||||||
ImportService,
|
ImportService,
|
||||||
} from "@bitwarden/importer";
|
} from "@bitwarden/importer/core";
|
||||||
|
|
||||||
import { BrowserOrganizationService } from "../admin-console/services/browser-organization.service";
|
import { BrowserOrganizationService } from "../admin-console/services/browser-organization.service";
|
||||||
import { BrowserPolicyService } from "../admin-console/services/browser-policy.service";
|
import { BrowserPolicyService } from "../admin-console/services/browser-policy.service";
|
||||||
|
@ -84,7 +84,7 @@ import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.serv
|
|||||||
import { FolderApiService } from "@bitwarden/common/vault/services/folder/folder-api.service";
|
import { FolderApiService } from "@bitwarden/common/vault/services/folder/folder-api.service";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import { DialogService } from "@bitwarden/components";
|
||||||
import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export";
|
import { VaultExportServiceAbstraction } from "@bitwarden/exporter/vault-export";
|
||||||
import { ImportServiceAbstraction } from "@bitwarden/importer";
|
import { ImportServiceAbstraction } from "@bitwarden/importer/core";
|
||||||
|
|
||||||
import { BrowserOrganizationService } from "../../admin-console/services/browser-organization.service";
|
import { BrowserOrganizationService } from "../../admin-console/services/browser-organization.service";
|
||||||
import { BrowserPolicyService } from "../../admin-console/services/browser-policy.service";
|
import { BrowserPolicyService } from "../../admin-console/services/browser-policy.service";
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ImportApiService, ImportApiServiceAbstraction } from "@bitwarden/importer";
|
import { ImportApiService, ImportApiServiceAbstraction } from "@bitwarden/importer/core";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ApiServiceInitOptions,
|
ApiServiceInitOptions,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ImportService, ImportServiceAbstraction } from "@bitwarden/importer";
|
import { ImportService, ImportServiceAbstraction } from "@bitwarden/importer/core";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
cryptoServiceFactory,
|
cryptoServiceFactory,
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
||||||
"@bitwarden/components": ["../../libs/components/src"],
|
"@bitwarden/components": ["../../libs/components/src"],
|
||||||
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
||||||
"@bitwarden/importer": ["../../libs/importer/src"],
|
"@bitwarden/importer/core": ["../../libs/importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
|
||||||
"@bitwarden/vault": ["../../libs/vault/src"]
|
"@bitwarden/vault": ["../../libs/vault/src"]
|
||||||
},
|
},
|
||||||
"useDefineForClassFields": false
|
"useDefineForClassFields": false
|
||||||
|
@ -74,7 +74,7 @@ import {
|
|||||||
ImportApiServiceAbstraction,
|
ImportApiServiceAbstraction,
|
||||||
ImportService,
|
ImportService,
|
||||||
ImportServiceAbstraction,
|
ImportServiceAbstraction,
|
||||||
} from "@bitwarden/importer";
|
} from "@bitwarden/importer/core";
|
||||||
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
import { NodeCryptoFunctionService } from "@bitwarden/node/services/node-crypto-function.service";
|
||||||
|
|
||||||
import { CliConfigService } from "./platform/services/cli-config.service";
|
import { CliConfigService } from "./platform/services/cli-config.service";
|
||||||
|
@ -3,7 +3,7 @@ import * as inquirer from "inquirer";
|
|||||||
|
|
||||||
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 { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { ImportServiceAbstraction, ImportType } from "@bitwarden/importer";
|
import { ImportServiceAbstraction, ImportType } from "@bitwarden/importer/core";
|
||||||
|
|
||||||
import { Response } from "../models/response";
|
import { Response } from "../models/response";
|
||||||
import { MessageResponse } from "../models/response/message.response";
|
import { MessageResponse } from "../models/response/message.response";
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"paths": {
|
"paths": {
|
||||||
"@bitwarden/common/spec": ["../../libs/common/spec"],
|
"@bitwarden/common/spec": ["../../libs/common/spec"],
|
||||||
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
||||||
"@bitwarden/importer": ["../../libs/importer/src"],
|
"@bitwarden/importer/core": ["../../libs/importer/src"],
|
||||||
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
||||||
"@bitwarden/node/*": ["../../libs/node/src/*"]
|
"@bitwarden/node/*": ["../../libs/node/src/*"]
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
||||||
"@bitwarden/components": ["../../libs/components/src"],
|
"@bitwarden/components": ["../../libs/components/src"],
|
||||||
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
||||||
"@bitwarden/importer": ["../../libs/importer/src"],
|
"@bitwarden/importer/core": ["../../libs/importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
|
||||||
"@bitwarden/vault": ["../../libs/vault/src"]
|
"@bitwarden/vault": ["../../libs/vault/src"]
|
||||||
},
|
},
|
||||||
"useDefineForClassFields": false
|
"useDefineForClassFields": false
|
||||||
|
@ -48,8 +48,15 @@ const routes: Routes = [
|
|||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "import",
|
path: "import",
|
||||||
loadChildren: () =>
|
loadComponent: () =>
|
||||||
import("../tools/import/org-import.module").then((m) => m.OrganizationImportModule),
|
import("../../../tools/import/import-web.component").then(
|
||||||
|
(mod) => mod.ImportWebComponent
|
||||||
|
),
|
||||||
|
canActivate: [OrganizationPermissionsGuard],
|
||||||
|
data: {
|
||||||
|
titleId: "importData",
|
||||||
|
organizationPermissions: (org: Organization) => org.canAccessImportExport,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "export",
|
path: "export",
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
import { NgModule } from "@angular/core";
|
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
|
||||||
|
|
||||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
|
||||||
|
|
||||||
import { OrganizationPermissionsGuard } from "../../guards/org-permissions.guard";
|
|
||||||
|
|
||||||
import { OrganizationImportComponent } from "./org-import.component";
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: "",
|
|
||||||
component: OrganizationImportComponent,
|
|
||||||
canActivate: [OrganizationPermissionsGuard],
|
|
||||||
data: {
|
|
||||||
titleId: "importData",
|
|
||||||
organizationPermissions: (org: Organization) => org.canAccessImportExport,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
})
|
|
||||||
export class OrganizationImportRoutingModule {}
|
|
@ -1,99 +0,0 @@
|
|||||||
import { Component } from "@angular/core";
|
|
||||||
import { FormBuilder } from "@angular/forms";
|
|
||||||
import { ActivatedRoute, Router } from "@angular/router";
|
|
||||||
import { switchMap, takeUntil } from "rxjs/operators";
|
|
||||||
|
|
||||||
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 { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
|
||||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
|
||||||
import { DialogService } from "@bitwarden/components";
|
|
||||||
import { ImportServiceAbstraction } from "@bitwarden/importer";
|
|
||||||
|
|
||||||
import { ImportComponent } from "../../../../tools/import/import.component";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: "app-org-import",
|
|
||||||
templateUrl: "../../../../tools/import/import.component.html",
|
|
||||||
})
|
|
||||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
|
||||||
export class OrganizationImportComponent extends ImportComponent {
|
|
||||||
organization: Organization;
|
|
||||||
|
|
||||||
protected get importBlockedByPolicy(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
i18nService: I18nService,
|
|
||||||
importService: ImportServiceAbstraction,
|
|
||||||
router: Router,
|
|
||||||
private route: ActivatedRoute,
|
|
||||||
platformUtilsService: PlatformUtilsService,
|
|
||||||
policyService: PolicyService,
|
|
||||||
organizationService: OrganizationService,
|
|
||||||
logService: LogService,
|
|
||||||
syncService: SyncService,
|
|
||||||
dialogService: DialogService,
|
|
||||||
folderService: FolderService,
|
|
||||||
collectionService: CollectionService,
|
|
||||||
formBuilder: FormBuilder
|
|
||||||
) {
|
|
||||||
super(
|
|
||||||
i18nService,
|
|
||||||
importService,
|
|
||||||
router,
|
|
||||||
platformUtilsService,
|
|
||||||
policyService,
|
|
||||||
logService,
|
|
||||||
syncService,
|
|
||||||
dialogService,
|
|
||||||
folderService,
|
|
||||||
collectionService,
|
|
||||||
organizationService,
|
|
||||||
formBuilder
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
this.route.params
|
|
||||||
.pipe(
|
|
||||||
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
|
||||||
takeUntil(this.destroy$)
|
|
||||||
)
|
|
||||||
.subscribe((organization) => {
|
|
||||||
this.organizationId = organization.id;
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async performImport() {
|
|
||||||
const confirmed = await this.dialogService.openSimpleDialog({
|
|
||||||
title: { key: "warning" },
|
|
||||||
content: { key: "importWarning", placeholders: [this.organization.name] },
|
|
||||||
type: "warning",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!confirmed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await super.performImport();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { NgModule } from "@angular/core";
|
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
|
||||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
|
||||||
import {
|
|
||||||
ImportService,
|
|
||||||
ImportServiceAbstraction,
|
|
||||||
ImportApiService,
|
|
||||||
ImportApiServiceAbstraction,
|
|
||||||
} from "@bitwarden/importer";
|
|
||||||
|
|
||||||
import { LooseComponentsModule, SharedModule } from "../../../../shared";
|
|
||||||
|
|
||||||
import { OrganizationImportRoutingModule } from "./org-import-routing.module";
|
|
||||||
import { OrganizationImportComponent } from "./org-import.component";
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [SharedModule, LooseComponentsModule, OrganizationImportRoutingModule],
|
|
||||||
declarations: [OrganizationImportComponent],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: ImportApiServiceAbstraction,
|
|
||||||
useClass: ImportApiService,
|
|
||||||
deps: [ApiService],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: ImportServiceAbstraction,
|
|
||||||
useClass: ImportService,
|
|
||||||
deps: [
|
|
||||||
CipherService,
|
|
||||||
FolderService,
|
|
||||||
ImportApiServiceAbstraction,
|
|
||||||
I18nService,
|
|
||||||
CollectionService,
|
|
||||||
CryptoService,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class OrganizationImportModule {}
|
|
@ -255,7 +255,11 @@ const routes: Routes = [
|
|||||||
{ path: "", pathMatch: "full", redirectTo: "generator" },
|
{ path: "", pathMatch: "full", redirectTo: "generator" },
|
||||||
{
|
{
|
||||||
path: "import",
|
path: "import",
|
||||||
loadChildren: () => import("./tools/import/import.module").then((m) => m.ImportModule),
|
loadComponent: () =>
|
||||||
|
import("./tools/import/import-web.component").then((mod) => mod.ImportWebComponent),
|
||||||
|
data: {
|
||||||
|
titleId: "importData",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "export",
|
path: "export",
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
import { DialogRef } from "@angular/cdk/dialog";
|
|
||||||
import { Component } from "@angular/core";
|
|
||||||
import { FormControl, Validators } from "@angular/forms";
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
templateUrl: "file-password-prompt.component.html",
|
|
||||||
})
|
|
||||||
export class FilePasswordPromptComponent {
|
|
||||||
filePassword = new FormControl("", Validators.required);
|
|
||||||
|
|
||||||
constructor(public dialogRef: DialogRef) {}
|
|
||||||
|
|
||||||
submit() {
|
|
||||||
this.filePassword.markAsTouched();
|
|
||||||
if (!this.filePassword.valid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.dialogRef.close(this.filePassword.value);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import { NgModule } from "@angular/core";
|
|
||||||
import { RouterModule, Routes } from "@angular/router";
|
|
||||||
|
|
||||||
import { ImportComponent } from "./import.component";
|
|
||||||
|
|
||||||
const routes: Routes = [
|
|
||||||
{
|
|
||||||
path: "",
|
|
||||||
component: ImportComponent,
|
|
||||||
data: { titleId: "importData" },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [RouterModule.forChild(routes)],
|
|
||||||
})
|
|
||||||
export class ImportRoutingModule {}
|
|
18
apps/web/src/app/tools/import/import-web.component.html
Normal file
18
apps/web/src/app/tools/import/import-web.component.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<h1 bitTypography="h1">{{ "importData" | i18n }}</h1>
|
||||||
|
<tools-import
|
||||||
|
(formDisabled)="this.disabled = $event"
|
||||||
|
(formLoading)="this.loading = $event"
|
||||||
|
(onSuccessfulImport)="this.onSuccessfulImport($event)"
|
||||||
|
organizationId="{{ routeOrgId }}"
|
||||||
|
></tools-import>
|
||||||
|
<button
|
||||||
|
[disabled]="disabled"
|
||||||
|
[loading]="loading"
|
||||||
|
form="importForm"
|
||||||
|
bitButton
|
||||||
|
type="submit"
|
||||||
|
bitFormButton
|
||||||
|
buttonType="primary"
|
||||||
|
>
|
||||||
|
{{ "importData" | i18n }}
|
||||||
|
</button>
|
51
apps/web/src/app/tools/import/import-web.component.ts
Normal file
51
apps/web/src/app/tools/import/import-web.component.ts
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { ActivatedRoute, Router } from "@angular/router";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import {
|
||||||
|
OrganizationService,
|
||||||
|
canAccessVaultTab,
|
||||||
|
} from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||||
|
import { ImportComponent } from "@bitwarden/importer/ui";
|
||||||
|
|
||||||
|
import { SharedModule } from "../../shared";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "import-web.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [SharedModule, ImportComponent],
|
||||||
|
})
|
||||||
|
export class ImportWebComponent implements OnInit {
|
||||||
|
protected routeOrgId: string = null;
|
||||||
|
protected loading = false;
|
||||||
|
protected disabled = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private organizationService: OrganizationService,
|
||||||
|
private router: Router
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.routeOrgId = this.route.snapshot.paramMap.get("organizationId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback that is called after a successful import.
|
||||||
|
*/
|
||||||
|
protected async onSuccessfulImport(organizationId: string): Promise<void> {
|
||||||
|
if (!organizationId) {
|
||||||
|
await this.router.navigate(["vault"]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const organization = await firstValueFrom(this.organizationService.get$(organizationId));
|
||||||
|
if (organization == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canAccessVaultTab(organization)) {
|
||||||
|
await this.router.navigate(["organizations", organizationId, "vault"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,54 +0,0 @@
|
|||||||
import { NgModule } from "@angular/core";
|
|
||||||
|
|
||||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
|
||||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
|
||||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
|
||||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
|
||||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
|
||||||
import {
|
|
||||||
ImportService,
|
|
||||||
ImportServiceAbstraction,
|
|
||||||
ImportApiService,
|
|
||||||
ImportApiServiceAbstraction,
|
|
||||||
} from "@bitwarden/importer";
|
|
||||||
|
|
||||||
import { LooseComponentsModule, SharedModule } from "../../shared";
|
|
||||||
|
|
||||||
import {
|
|
||||||
ImportErrorDialogComponent,
|
|
||||||
ImportSuccessDialogComponent,
|
|
||||||
FilePasswordPromptComponent,
|
|
||||||
} from "./dialog";
|
|
||||||
import { ImportRoutingModule } from "./import-routing.module";
|
|
||||||
import { ImportComponent } from "./import.component";
|
|
||||||
|
|
||||||
@NgModule({
|
|
||||||
imports: [SharedModule, LooseComponentsModule, ImportRoutingModule],
|
|
||||||
declarations: [
|
|
||||||
ImportComponent,
|
|
||||||
FilePasswordPromptComponent,
|
|
||||||
ImportErrorDialogComponent,
|
|
||||||
ImportSuccessDialogComponent,
|
|
||||||
],
|
|
||||||
providers: [
|
|
||||||
{
|
|
||||||
provide: ImportApiServiceAbstraction,
|
|
||||||
useClass: ImportApiService,
|
|
||||||
deps: [ApiService],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
provide: ImportServiceAbstraction,
|
|
||||||
useClass: ImportService,
|
|
||||||
deps: [
|
|
||||||
CipherService,
|
|
||||||
FolderService,
|
|
||||||
ImportApiServiceAbstraction,
|
|
||||||
I18nService,
|
|
||||||
CollectionService,
|
|
||||||
CryptoService,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
})
|
|
||||||
export class ImportModule {}
|
|
@ -32,7 +32,7 @@ app-password-generator-history {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app-import {
|
tools-import {
|
||||||
textarea {
|
textarea {
|
||||||
height: 150px;
|
height: 150px;
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
"@bitwarden/common/*": ["../../libs/common/src/*"],
|
||||||
"@bitwarden/components": ["../../libs/components/src"],
|
"@bitwarden/components": ["../../libs/components/src"],
|
||||||
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["../../libs/exporter/src/*"],
|
||||||
"@bitwarden/importer": ["../../libs/importer/src"],
|
"@bitwarden/importer/core": ["../../libs/importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["../../libs/importer/src/components"],
|
||||||
"@bitwarden/vault": ["../../libs/vault/src"],
|
"@bitwarden/vault": ["../../libs/vault/src"],
|
||||||
"@bitwarden/web-vault/*": ["src/*"]
|
"@bitwarden/web-vault/*": ["src/*"]
|
||||||
}
|
}
|
||||||
|
@ -154,7 +154,7 @@ import {
|
|||||||
ImportApiServiceAbstraction,
|
ImportApiServiceAbstraction,
|
||||||
ImportService,
|
ImportService,
|
||||||
ImportServiceAbstraction,
|
ImportServiceAbstraction,
|
||||||
} from "@bitwarden/importer";
|
} from "@bitwarden/importer/core";
|
||||||
import { PasswordRepromptService } from "@bitwarden/vault";
|
import { PasswordRepromptService } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { AuthGuard } from "../auth/guards/auth.guard";
|
import { AuthGuard } from "../auth/guards/auth.guard";
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
export * from "./async-actions.module";
|
export * from "./async-actions.module";
|
||||||
export * from "./bit-action.directive";
|
export * from "./bit-action.directive";
|
||||||
export * from "./form-button.directive";
|
export * from "./form-button.directive";
|
||||||
|
export * from "./bit-submit.directive";
|
||||||
|
4
libs/components/src/table/table.component.css
Normal file
4
libs/components/src/table/table.component.css
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
th {
|
||||||
|
text-align: inherit;
|
||||||
|
text-align: -webkit-match-parent;
|
||||||
|
}
|
@ -39,6 +39,8 @@ export class TableComponent implements OnDestroy, AfterContentChecked {
|
|||||||
"tw-w-full",
|
"tw-w-full",
|
||||||
"tw-leading-normal",
|
"tw-leading-normal",
|
||||||
"tw-text-main",
|
"tw-text-main",
|
||||||
|
"tw-border-collapse",
|
||||||
|
"tw-text-start",
|
||||||
this.layout === "auto" ? "tw-table-auto" : "tw-table-fixed",
|
this.layout === "auto" ? "tw-table-auto" : "tw-table-fixed",
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -159,6 +159,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@import "./search/search.component.css";
|
@import "./search/search.component.css";
|
||||||
|
@import "./table/table.component.css";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tw-break-words does not work with table cells:
|
* tw-break-words does not work with table cells:
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
<form (submit)="submit()">
|
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||||
<bit-dialog>
|
<bit-dialog>
|
||||||
<span bitDialogTitle>
|
<span bitDialogTitle>
|
||||||
{{ "confirmVaultImport" | i18n }}
|
{{ "confirmVaultImport" | i18n }}
|
||||||
@ -12,7 +12,7 @@
|
|||||||
bitInput
|
bitInput
|
||||||
type="password"
|
type="password"
|
||||||
name="filePassword"
|
name="filePassword"
|
||||||
[formControl]="filePassword"
|
formControlName="filePassword"
|
||||||
appAutofocus
|
appAutofocus
|
||||||
appInputVerbatim
|
appInputVerbatim
|
||||||
/>
|
/>
|
@ -0,0 +1,43 @@
|
|||||||
|
import { DialogRef } from "@angular/cdk/dialog";
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
|
import { Component } from "@angular/core";
|
||||||
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import {
|
||||||
|
AsyncActionsModule,
|
||||||
|
ButtonModule,
|
||||||
|
DialogModule,
|
||||||
|
FormFieldModule,
|
||||||
|
IconButtonModule,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: "file-password-prompt.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
DialogModule,
|
||||||
|
FormFieldModule,
|
||||||
|
AsyncActionsModule,
|
||||||
|
ButtonModule,
|
||||||
|
IconButtonModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class FilePasswordPromptComponent {
|
||||||
|
formGroup = this.formBuilder.group({
|
||||||
|
filePassword: ["", Validators.required],
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(public dialogRef: DialogRef, protected formBuilder: FormBuilder) {}
|
||||||
|
|
||||||
|
submit = () => {
|
||||||
|
this.formGroup.markAsTouched();
|
||||||
|
if (!this.formGroup.valid) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.dialogRef.close(this.formGroup.value.filePassword);
|
||||||
|
};
|
||||||
|
}
|
@ -1,7 +1,9 @@
|
|||||||
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, Inject, OnInit } from "@angular/core";
|
import { Component, Inject, OnInit } from "@angular/core";
|
||||||
|
|
||||||
import { TableDataSource } from "@bitwarden/components";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { ButtonModule, DialogModule, TableDataSource, TableModule } from "@bitwarden/components";
|
||||||
|
|
||||||
export interface ErrorListItem {
|
export interface ErrorListItem {
|
||||||
type: string;
|
type: string;
|
||||||
@ -9,8 +11,9 @@ export interface ErrorListItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-import-error-dialog",
|
|
||||||
templateUrl: "./import-error-dialog.component.html",
|
templateUrl: "./import-error-dialog.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, JslibModule, DialogModule, TableModule, ButtonModule],
|
||||||
})
|
})
|
||||||
export class ImportErrorDialogComponent implements OnInit {
|
export class ImportErrorDialogComponent implements OnInit {
|
||||||
protected dataSource = new TableDataSource<ErrorListItem>();
|
protected dataSource = new TableDataSource<ErrorListItem>();
|
@ -1,9 +1,12 @@
|
|||||||
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
import { DialogRef, DIALOG_DATA } from "@angular/cdk/dialog";
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, Inject, OnInit } from "@angular/core";
|
import { Component, Inject, OnInit } from "@angular/core";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
import { CipherType } from "@bitwarden/common/vault/enums/cipher-type";
|
||||||
import { TableDataSource } from "@bitwarden/components";
|
import { ButtonModule, DialogModule, TableDataSource, TableModule } from "@bitwarden/components";
|
||||||
import { ImportResult } from "@bitwarden/importer";
|
|
||||||
|
import { ImportResult } from "../../models";
|
||||||
|
|
||||||
export interface ResultList {
|
export interface ResultList {
|
||||||
icon: string;
|
icon: string;
|
||||||
@ -13,6 +16,8 @@ export interface ResultList {
|
|||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
templateUrl: "./import-success-dialog.component.html",
|
templateUrl: "./import-success-dialog.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule, JslibModule, DialogModule, TableModule, ButtonModule],
|
||||||
})
|
})
|
||||||
export class ImportSuccessDialogComponent implements OnInit {
|
export class ImportSuccessDialogComponent implements OnInit {
|
||||||
protected dataSource = new TableDataSource<ResultList>();
|
protected dataSource = new TableDataSource<ResultList>();
|
@ -1,9 +1,7 @@
|
|||||||
<h1 bitTypography="h1">{{ "importData" | i18n }}</h1>
|
|
||||||
|
|
||||||
<bit-callout type="info" *ngIf="importBlockedByPolicy">
|
<bit-callout type="info" *ngIf="importBlockedByPolicy">
|
||||||
{{ "personalOwnershipPolicyInEffectImports" | i18n }}
|
{{ "personalOwnershipPolicyInEffectImports" | i18n }}
|
||||||
</bit-callout>
|
</bit-callout>
|
||||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
<form [formGroup]="formGroup" [bitSubmit]="submit" id="importForm">
|
||||||
<bit-form-field>
|
<bit-form-field>
|
||||||
<bit-label
|
<bit-label
|
||||||
>{{ "importDestination" | i18n }}
|
>{{ "importDestination" | i18n }}
|
||||||
@ -349,12 +347,7 @@
|
|||||||
<bit-form-field>
|
<bit-form-field>
|
||||||
<bit-label>{{ "selectImportFile" | i18n }}</bit-label>
|
<bit-label>{{ "selectImportFile" | i18n }}</bit-label>
|
||||||
<div class="file-selector">
|
<div class="file-selector">
|
||||||
<button
|
<button bitButton type="button" buttonType="secondary" (click)="fileSelector.click()">
|
||||||
bitButton
|
|
||||||
type="button"
|
|
||||||
class="btn btn-outline-primary"
|
|
||||||
(click)="fileSelector.click()"
|
|
||||||
>
|
|
||||||
{{ "chooseFile" | i18n }}
|
{{ "chooseFile" | i18n }}
|
||||||
</button>
|
</button>
|
||||||
{{ this.fileSelected ? this.fileSelected.name : ("noFileChosen" | i18n) }}
|
{{ this.fileSelected ? this.fileSelected.name : ("noFileChosen" | i18n) }}
|
||||||
@ -380,13 +373,4 @@
|
|||||||
formControlName="fileContents"
|
formControlName="fileContents"
|
||||||
></textarea>
|
></textarea>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
<button
|
|
||||||
bitButton
|
|
||||||
bitFormButton
|
|
||||||
type="submit"
|
|
||||||
buttonType="primary"
|
|
||||||
[disabled]="importBlockedByPolicy"
|
|
||||||
>
|
|
||||||
{{ "importData" | i18n }}
|
|
||||||
</button>
|
|
||||||
</form>
|
</form>
|
@ -1,10 +1,20 @@
|
|||||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
import { CommonModule } from "@angular/common";
|
||||||
import { FormBuilder, Validators } from "@angular/forms";
|
import {
|
||||||
import { Router } from "@angular/router";
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewChild,
|
||||||
|
} from "@angular/core";
|
||||||
|
import { FormBuilder, ReactiveFormsModule, Validators } from "@angular/forms";
|
||||||
import * as JSZip from "jszip";
|
import * as JSZip from "jszip";
|
||||||
import { concat, Observable, Subject, lastValueFrom, combineLatest } from "rxjs";
|
import { concat, Observable, Subject, lastValueFrom, combineLatest } from "rxjs";
|
||||||
import { map, takeUntil } from "rxjs/operators";
|
import { map, takeUntil } from "rxjs/operators";
|
||||||
|
|
||||||
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||||
import {
|
import {
|
||||||
canAccessImportExport,
|
canAccessImportExport,
|
||||||
OrganizationService,
|
OrganizationService,
|
||||||
@ -12,22 +22,35 @@ import {
|
|||||||
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 { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.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";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||||
|
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||||
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
import { FolderService } from "@bitwarden/common/vault/abstractions/folder/folder.service.abstraction";
|
||||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||||
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
import { FolderView } from "@bitwarden/common/vault/models/view/folder.view";
|
||||||
import { DialogService } from "@bitwarden/components";
|
|
||||||
import {
|
import {
|
||||||
ImportOption,
|
AsyncActionsModule,
|
||||||
ImportResult,
|
BitSubmitDirective,
|
||||||
|
ButtonModule,
|
||||||
|
CalloutModule,
|
||||||
|
DialogService,
|
||||||
|
FormFieldModule,
|
||||||
|
IconButtonModule,
|
||||||
|
SelectModule,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
|
import { ImportOption, ImportResult, ImportType } from "../models";
|
||||||
|
import {
|
||||||
|
ImportApiService,
|
||||||
|
ImportApiServiceAbstraction,
|
||||||
|
ImportService,
|
||||||
ImportServiceAbstraction,
|
ImportServiceAbstraction,
|
||||||
ImportType,
|
} from "../services";
|
||||||
} from "@bitwarden/importer";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FilePasswordPromptComponent,
|
FilePasswordPromptComponent,
|
||||||
@ -36,8 +59,39 @@ import {
|
|||||||
} from "./dialog";
|
} from "./dialog";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-import",
|
selector: "tools-import",
|
||||||
templateUrl: "import.component.html",
|
templateUrl: "import.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
JslibModule,
|
||||||
|
FormFieldModule,
|
||||||
|
AsyncActionsModule,
|
||||||
|
ButtonModule,
|
||||||
|
IconButtonModule,
|
||||||
|
SelectModule,
|
||||||
|
CalloutModule,
|
||||||
|
ReactiveFormsModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: ImportApiServiceAbstraction,
|
||||||
|
useClass: ImportApiService,
|
||||||
|
deps: [ApiService],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: ImportServiceAbstraction,
|
||||||
|
useClass: ImportService,
|
||||||
|
deps: [
|
||||||
|
CipherService,
|
||||||
|
FolderService,
|
||||||
|
ImportApiServiceAbstraction,
|
||||||
|
I18nService,
|
||||||
|
CollectionService,
|
||||||
|
CryptoService,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class ImportComponent implements OnInit, OnDestroy {
|
export class ImportComponent implements OnInit, OnDestroy {
|
||||||
featuredImportOptions: ImportOption[];
|
featuredImportOptions: ImportOption[];
|
||||||
@ -49,7 +103,24 @@ export class ImportComponent implements OnInit, OnDestroy {
|
|||||||
collections$: Observable<CollectionView[]>;
|
collections$: Observable<CollectionView[]>;
|
||||||
organizations$: Observable<Organization[]>;
|
organizations$: Observable<Organization[]>;
|
||||||
|
|
||||||
protected organizationId: string = null;
|
private _organizationId: string;
|
||||||
|
|
||||||
|
get organizationId(): string {
|
||||||
|
return this._organizationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Input() set organizationId(value: string) {
|
||||||
|
this._organizationId = value;
|
||||||
|
this.organizationService
|
||||||
|
.get$(this._organizationId)
|
||||||
|
.pipe(takeUntil(this.destroy$))
|
||||||
|
.subscribe((organization) => {
|
||||||
|
this._organizationId = organization?.id;
|
||||||
|
this.organization = organization;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected organization: Organization;
|
||||||
protected destroy$ = new Subject<void>();
|
protected destroy$ = new Subject<void>();
|
||||||
|
|
||||||
private _importBlockedByPolicy = false;
|
private _importBlockedByPolicy = false;
|
||||||
@ -68,10 +139,31 @@ export class ImportComponent implements OnInit, OnDestroy {
|
|||||||
file: [],
|
file: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ViewChild(BitSubmitDirective)
|
||||||
|
private bitSubmit: BitSubmitDirective;
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
formLoading = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
formDisabled = new EventEmitter<boolean>();
|
||||||
|
|
||||||
|
@Output()
|
||||||
|
onSuccessfulImport = new EventEmitter<string>();
|
||||||
|
|
||||||
|
ngAfterViewInit(): void {
|
||||||
|
this.bitSubmit.loading$.pipe(takeUntil(this.destroy$)).subscribe((loading) => {
|
||||||
|
this.formLoading.emit(loading);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.bitSubmit.disabled$.pipe(takeUntil(this.destroy$)).subscribe((disabled) => {
|
||||||
|
this.formDisabled.emit(disabled);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected i18nService: I18nService,
|
protected i18nService: I18nService,
|
||||||
protected importService: ImportServiceAbstraction,
|
protected importService: ImportServiceAbstraction,
|
||||||
protected router: Router,
|
|
||||||
protected platformUtilsService: PlatformUtilsService,
|
protected platformUtilsService: PlatformUtilsService,
|
||||||
protected policyService: PolicyService,
|
protected policyService: PolicyService,
|
||||||
private logService: LogService,
|
private logService: LogService,
|
||||||
@ -87,13 +179,6 @@ export class ImportComponent implements OnInit, OnDestroy {
|
|||||||
return this._importBlockedByPolicy;
|
return this._importBlockedByPolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback that is called after a successful import.
|
|
||||||
*/
|
|
||||||
protected async onSuccessfulImport(): Promise<void> {
|
|
||||||
await this.router.navigate(["vault"]);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.setImportOptions();
|
this.setImportOptions();
|
||||||
|
|
||||||
@ -167,6 +252,18 @@ export class ImportComponent implements OnInit, OnDestroy {
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected async performImport() {
|
protected async performImport() {
|
||||||
|
if (this.organization) {
|
||||||
|
const confirmed = await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "warning" },
|
||||||
|
content: { key: "importWarning", placeholders: [this.organization.name] },
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.importBlockedByPolicy) {
|
if (this.importBlockedByPolicy) {
|
||||||
this.platformUtilsService.showToast(
|
this.platformUtilsService.showToast(
|
||||||
"error",
|
"error",
|
||||||
@ -246,7 +343,7 @@ export class ImportComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.syncService.fullSync(true);
|
this.syncService.fullSync(true);
|
||||||
await this.onSuccessfulImport();
|
this.onSuccessfulImport.emit(this._organizationId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.dialogService.open<unknown, Error>(ImportErrorDialogComponent, {
|
this.dialogService.open<unknown, Error>(ImportErrorDialogComponent, {
|
||||||
data: e,
|
data: e,
|
3
libs/importer/src/components/index.ts
Normal file
3
libs/importer/src/components/index.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
export * from "./dialog";
|
||||||
|
|
||||||
|
export { ImportComponent } from "./import.component";
|
@ -1,11 +1,5 @@
|
|||||||
export { ImportType, ImportOption } from "./models/import-options";
|
export * from "./models";
|
||||||
|
|
||||||
export { ImportResult } from "./models/import-result";
|
export * from "./services";
|
||||||
|
|
||||||
export { ImportApiServiceAbstraction } from "./services/import-api.service.abstraction";
|
|
||||||
export { ImportApiService } from "./services/import-api.service";
|
|
||||||
|
|
||||||
export { ImportServiceAbstraction } from "./services/import.service.abstraction";
|
|
||||||
export { ImportService } from "./services/import.service";
|
|
||||||
|
|
||||||
export { Importer } from "./importers/importer";
|
export { Importer } from "./importers/importer";
|
||||||
|
2
libs/importer/src/models/index.ts
Normal file
2
libs/importer/src/models/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export { ImportType, ImportOption } from "./import-options";
|
||||||
|
export { ImportResult } from "./import-result";
|
5
libs/importer/src/services/index.ts
Normal file
5
libs/importer/src/services/index.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export { ImportApiServiceAbstraction } from "./import-api.service.abstraction";
|
||||||
|
export { ImportApiService } from "./import-api.service";
|
||||||
|
|
||||||
|
export { ImportServiceAbstraction } from "./import.service.abstraction";
|
||||||
|
export { ImportService } from "./import.service";
|
@ -7,7 +7,8 @@
|
|||||||
"@bitwarden/common/*": ["../common/src/*"],
|
"@bitwarden/common/*": ["../common/src/*"],
|
||||||
"@bitwarden/components": ["../components/src"],
|
"@bitwarden/components": ["../components/src"],
|
||||||
"@bitwarden/exporter/*": ["../exporter/src/*"],
|
"@bitwarden/exporter/*": ["../exporter/src/*"],
|
||||||
"@bitwarden/importer": ["../importer/src"],
|
"@bitwarden/importer/core": ["../importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["../importer/src/components"],
|
||||||
"@bitwarden/node/*": ["../node/src/*"],
|
"@bitwarden/node/*": ["../node/src/*"],
|
||||||
"@bitwarden/vault": ["../vault/src"]
|
"@bitwarden/vault": ["../vault/src"]
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
"@bitwarden/common/*": ["./libs/common/src/*"],
|
"@bitwarden/common/*": ["./libs/common/src/*"],
|
||||||
"@bitwarden/components": ["./libs/components/src"],
|
"@bitwarden/components": ["./libs/components/src"],
|
||||||
"@bitwarden/exporter/*": ["./libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["./libs/exporter/src/*"],
|
||||||
"@bitwarden/importer": ["./libs/importer/src"],
|
"@bitwarden/importer/core": ["./libs/importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["./libs/importer/src/components"],
|
||||||
"@bitwarden/node/*": ["./libs/node/src/*"],
|
"@bitwarden/node/*": ["./libs/node/src/*"],
|
||||||
"@bitwarden/vault": ["./libs/vault/src"]
|
"@bitwarden/vault": ["./libs/vault/src"]
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
"@bitwarden/common/*": ["./libs/common/src/*"],
|
"@bitwarden/common/*": ["./libs/common/src/*"],
|
||||||
"@bitwarden/components": ["./libs/components/src"],
|
"@bitwarden/components": ["./libs/components/src"],
|
||||||
"@bitwarden/exporter/*": ["./libs/exporter/src/*"],
|
"@bitwarden/exporter/*": ["./libs/exporter/src/*"],
|
||||||
"@bitwarden/importer": ["./libs/importer/src"],
|
"@bitwarden/importer/core": ["./libs/importer/src"],
|
||||||
|
"@bitwarden/importer/ui": ["./libs/importer/src/components"],
|
||||||
"@bitwarden/node/*": ["./libs/node/src/*"],
|
"@bitwarden/node/*": ["./libs/node/src/*"],
|
||||||
"@bitwarden/web-vault/*": ["./apps/web/src/*"],
|
"@bitwarden/web-vault/*": ["./apps/web/src/*"],
|
||||||
"@bitwarden/vault": ["./libs/vault/src"]
|
"@bitwarden/vault": ["./libs/vault/src"]
|
||||||
|
Loading…
Reference in New Issue
Block a user