mirror of
https://github.com/bitwarden/browser
synced 2026-02-28 10:33:31 +00:00
Merge branch 'PS-55-EncryptedExport' into PS55-6-22
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()">
|
||||
<div class="tw-text-center bwi-3x">
|
||||
<i class="bwi bwi-exclamation-triangle text-warning"></i>
|
||||
</div>
|
||||
|
||||
<h2 class="tw-text-center tw-font-semibold" id="confirmUserTitle">
|
||||
{{ "confirmVaultImport" | i18n }}
|
||||
</h2>
|
||||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
{{ "confirmVaultImportDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="form-group modal-content">
|
||||
<label for="filePassword">{{ "confirmFilePassword" | i18n }}</label>
|
||||
<div>
|
||||
<div class="input-group">
|
||||
<input
|
||||
id="filePassword"
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
name="filePassword"
|
||||
class="text-monospace form-control"
|
||||
[(ngModel)]="filePassword"
|
||||
required
|
||||
appAutofocus
|
||||
appInputVerbatim
|
||||
/>
|
||||
|
||||
<div class="input-group-append">
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
(click)="togglePassword()"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tw-mt-4">
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{ "importData" | i18n }}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { FilePasswordPromptComponent as BaseFilePasswordPrompt } from "@bitwarden/angular/components/file-password-prompt.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "file-password-prompt.component.html",
|
||||
})
|
||||
export class FilePasswordPromptComponent extends BaseFilePasswordPrompt {}
|
||||
@@ -0,0 +1,36 @@
|
||||
<div class="modal fade" role="dialog" aria-modal="true" aria-labelledby="confirmUserTitle">
|
||||
<div class="modal-dialog modal-dialog-scrollable" role="document">
|
||||
<form class="modal-content" #form (ngSubmit)="submit()">
|
||||
<div class="tw-text-center bwi-3x">
|
||||
<i class="bwi bwi-exclamation-triangle text-warning"></i>
|
||||
</div>
|
||||
|
||||
<h2 class="tw-text-center tw-font-semibold" id="confirmUserTitle">
|
||||
{{ modalTitle | i18n }}
|
||||
</h2>
|
||||
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
{{ confirmDescription | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer-content">
|
||||
<div [formGroup]="myGroup">
|
||||
<div class="form-group">
|
||||
<app-user-verification ngDefaultControl formControlName="secret" name="secret">
|
||||
</app-user-verification>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary btn-submit" appBlurClick>
|
||||
<span>{{ confirmButtonText | i18n }}</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary" data-dismiss="modal">
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { UserVerificationPromptComponent as BaseUserVerificationPrompt } from "@bitwarden/angular/components/user-verification-prompt.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "user-verification-prompt.component.html",
|
||||
})
|
||||
export class UserVerificationPromptComponent extends BaseUserVerificationPrompt {}
|
||||
@@ -19,11 +19,13 @@ import { UpdatePasswordComponent } from "../accounts/update-password.component";
|
||||
import { UpdateTempPasswordComponent } from "../accounts/update-temp-password.component";
|
||||
import { VerifyEmailTokenComponent } from "../accounts/verify-email-token.component";
|
||||
import { VerifyRecoverDeleteComponent } from "../accounts/verify-recover-delete.component";
|
||||
import { FilePasswordPromptComponent } from "../components/file-password-prompt.component";
|
||||
import { NestedCheckboxComponent } from "../components/nested-checkbox.component";
|
||||
import { OrganizationSwitcherComponent } from "../components/organization-switcher.component";
|
||||
import { PasswordRepromptComponent } from "../components/password-reprompt.component";
|
||||
import { PasswordStrengthComponent } from "../components/password-strength.component";
|
||||
import { PremiumBadgeComponent } from "../components/premium-badge.component";
|
||||
import { UserVerificationPromptComponent } from "../components/user-verification-prompt.component";
|
||||
import { FooterComponent } from "../layouts/footer.component";
|
||||
import { FrontendLayoutComponent } from "../layouts/frontend-layout.component";
|
||||
import { NavbarComponent } from "../layouts/navbar.component";
|
||||
@@ -271,6 +273,8 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordGeneratorPolicyComponent,
|
||||
PasswordRepromptComponent,
|
||||
FilePasswordPromptComponent,
|
||||
UserVerificationPromptComponent,
|
||||
PasswordStrengthComponent,
|
||||
PaymentComponent,
|
||||
PaymentMethodComponent,
|
||||
@@ -430,6 +434,7 @@ import { OrganizationBadgeModule } from "./vault/modules/organization-badge/orga
|
||||
PasswordGeneratorHistoryComponent,
|
||||
PasswordGeneratorPolicyComponent,
|
||||
PasswordRepromptComponent,
|
||||
FilePasswordPromptComponent,
|
||||
PasswordStrengthComponent,
|
||||
PaymentComponent,
|
||||
PaymentMethodComponent,
|
||||
|
||||
@@ -2,6 +2,9 @@ import { Component } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { ModalConfig, ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { UserVerificationPromptService } from "@bitwarden/angular/services/userVerificationPrompt.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
@@ -9,6 +12,7 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
|
||||
|
||||
import { ExportComponent as BaseExportComponent } from "../../tools/export.component";
|
||||
@@ -28,7 +32,12 @@ export class ExportComponent extends BaseExportComponent {
|
||||
policyService: PolicyService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder
|
||||
formBuilder: FormBuilder,
|
||||
modalService: ModalService,
|
||||
apiService: ApiService,
|
||||
stateService: StateService,
|
||||
userVerificationPromptService: UserVerificationPromptService,
|
||||
modalConfig: ModalConfig
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@@ -39,7 +48,12 @@ export class ExportComponent extends BaseExportComponent {
|
||||
policyService,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
modalService,
|
||||
apiService,
|
||||
stateService,
|
||||
userVerificationPromptService,
|
||||
modalConfig
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { OrganizationService } from "@bitwarden/common/abstractions/organization.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
@@ -25,9 +27,20 @@ export class ImportComponent extends BaseImportComponent {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
policyService: PolicyService,
|
||||
private organizationService: OrganizationService,
|
||||
logService: LogService
|
||||
logService: LogService,
|
||||
modalService: ModalService,
|
||||
keyConnectorService: KeyConnectorService
|
||||
) {
|
||||
super(i18nService, importService, router, platformUtilsService, policyService, logService);
|
||||
super(
|
||||
i18nService,
|
||||
importService,
|
||||
router,
|
||||
platformUtilsService,
|
||||
policyService,
|
||||
logService,
|
||||
modalService,
|
||||
keyConnectorService
|
||||
);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
@@ -9,11 +9,17 @@ import {
|
||||
LOCALES_DIRECTORY,
|
||||
SYSTEM_LANGUAGE,
|
||||
} from "@bitwarden/angular/services/jslib-services.module";
|
||||
import { ModalService as ModalServiceAbstraction } from "@bitwarden/angular/services/modal.service";
|
||||
import {
|
||||
ModalService as ModalServiceAbstraction,
|
||||
ModalConfig as ModalConfigAbstraction,
|
||||
ModalConfig,
|
||||
} from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CipherService as CipherServiceAbstraction } from "@bitwarden/common/abstractions/cipher.service";
|
||||
import { CollectionService as CollectionServiceAbstraction } from "@bitwarden/common/abstractions/collection.service";
|
||||
import { CryptoService as CryptoServiceAbstraction } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/abstractions/cryptoFunction.service";
|
||||
import { ExportService as ExportServiceAbstraction } from "@bitwarden/common/abstractions/export.service";
|
||||
import { FolderService as FolderServiceAbstraction } from "@bitwarden/common/abstractions/folder.service";
|
||||
import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { ImportService as ImportServiceAbstraction } from "@bitwarden/common/abstractions/import.service";
|
||||
@@ -24,7 +30,9 @@ import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwar
|
||||
import { StateService as BaseStateServiceAbstraction } from "@bitwarden/common/abstractions/state.service";
|
||||
import { StateMigrationService as StateMigrationServiceAbstraction } from "@bitwarden/common/abstractions/stateMigration.service";
|
||||
import { StorageService as StorageServiceAbstraction } from "@bitwarden/common/abstractions/storage.service";
|
||||
import { UserVerificationPromptService as UserVerificationPromptServiceAbstraction } from "@bitwarden/common/abstractions/userVerificationPrompt.service";
|
||||
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
|
||||
import { ExportService } from "@bitwarden/common/services/export.service";
|
||||
import { ImportService } from "@bitwarden/common/services/import.service";
|
||||
|
||||
import { StateService as StateServiceAbstraction } from "../../abstractions/state.service";
|
||||
@@ -37,6 +45,7 @@ import { MemoryStorageService } from "../../services/memoryStorage.service";
|
||||
import { PasswordRepromptService } from "../../services/passwordReprompt.service";
|
||||
import { StateService } from "../../services/state.service";
|
||||
import { StateMigrationService } from "../../services/stateMigration.service";
|
||||
import { UserVerificationPromptService } from "../../services/userVerificationPrompt.service";
|
||||
import { WebPlatformUtilsService } from "../../services/webPlatformUtils.service";
|
||||
import { HomeGuard } from "../guards/home.guard";
|
||||
import { PermissionsGuard as OrgPermissionsGuard } from "../organizations/guards/permissions.guard";
|
||||
@@ -90,6 +99,7 @@ import { RouterService } from "./router.service";
|
||||
},
|
||||
{ provide: MessagingServiceAbstraction, useClass: BroadcasterMessagingService },
|
||||
{ provide: ModalServiceAbstraction, useClass: ModalService },
|
||||
{ provide: ModalConfigAbstraction, useClass: ModalConfig },
|
||||
{
|
||||
provide: ImportServiceAbstraction,
|
||||
useClass: ImportService,
|
||||
@@ -103,6 +113,17 @@ import { RouterService } from "./router.service";
|
||||
CryptoServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: ExportServiceAbstraction,
|
||||
useClass: ExportService,
|
||||
deps: [
|
||||
FolderServiceAbstraction,
|
||||
CipherServiceAbstraction,
|
||||
ApiServiceAbstraction,
|
||||
CryptoServiceAbstraction,
|
||||
CryptoFunctionServiceAbstraction,
|
||||
],
|
||||
},
|
||||
{
|
||||
provide: StateMigrationServiceAbstraction,
|
||||
useClass: StateMigrationService,
|
||||
@@ -128,6 +149,10 @@ import { RouterService } from "./router.service";
|
||||
provide: PasswordRepromptServiceAbstraction,
|
||||
useClass: PasswordRepromptService,
|
||||
},
|
||||
{
|
||||
provide: UserVerificationPromptServiceAbstraction,
|
||||
useClass: UserVerificationPromptService,
|
||||
},
|
||||
HomeGuard,
|
||||
],
|
||||
})
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
ngNativeValidate
|
||||
[appApiAction]="formPromise"
|
||||
[formGroup]="exportForm"
|
||||
*ngIf="exportForm"
|
||||
>
|
||||
<div class="page-header">
|
||||
<h1>{{ "exportVault" | i18n }}</h1>
|
||||
@@ -20,23 +21,123 @@
|
||||
<div class="row">
|
||||
<div class="form-group col-6">
|
||||
<label for="format">{{ "fileFormat" | i18n }}</label>
|
||||
<select class="form-control" id="format" name="Format" formControlName="format">
|
||||
<select class="form-control" name="format" formControlName="format">
|
||||
<option *ngFor="let f of formatOptions" [value]="f.value">{{ f.name }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-6">
|
||||
<app-user-verification ngDefaultControl formControlName="secret" name="secret">
|
||||
</app-user-verification>
|
||||
<ng-container *ngIf="format === 'encrypted_json'">
|
||||
<div role="radiogroup" aria-labelledby="fileTypeHeading">
|
||||
<label id="fileTypeHeading" class="radio-header">
|
||||
{{ "fileTypeHeading" | i18n }}
|
||||
</label>
|
||||
|
||||
<div appBoxRow name="FileTypeOptions">
|
||||
<input
|
||||
type="radio"
|
||||
class="radio"
|
||||
name="fileEncryptionType"
|
||||
id="1"
|
||||
[value]="0"
|
||||
formControlName="fileEncryptionType"
|
||||
/>
|
||||
<label class="unstyled"> {{ "accountBackup" | i18n }} </label>
|
||||
<div class="small text-muted" style="margin-left: 1.25em">
|
||||
{{ "accountBackupOptionDescription" | i18n }}
|
||||
</div>
|
||||
<input
|
||||
type="radio"
|
||||
class="radio"
|
||||
name="fileEncryptionType"
|
||||
id="2"
|
||||
[value]="1"
|
||||
formControlName="fileEncryptionType"
|
||||
/>
|
||||
|
||||
<label class="unstyled">{{ "passwordProtected" | i18n }}</label>
|
||||
<div class="small text-muted" style="margin-left: 1.25em">
|
||||
{{ "passwordProtectedOptionDescription" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</div>
|
||||
|
||||
<ng-container *ngIf="fileEncryptionType == 1">
|
||||
<label for="format">{{ "filePassword" | i18n }}</label>
|
||||
|
||||
<div class="input-group">
|
||||
<input
|
||||
type="{{ showPassword ? 'text' : 'password' }}"
|
||||
formControlName="password"
|
||||
name="password"
|
||||
class="form-control"
|
||||
/>
|
||||
<div class="input-group-append">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showPassword"
|
||||
(click)="togglePassword()"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{ 'bwi-eye': !showPassword, 'bwi-eye-slash': showPassword }"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="small text-muted">
|
||||
{{ "exportPasswordDescription" | i18n }}
|
||||
</div>
|
||||
<br />
|
||||
<label for="format">{{ "confirmFilePassword" | i18n }}</label>
|
||||
<div class="input-group">
|
||||
<input
|
||||
formControlName="confirmPassword"
|
||||
name="confirmPassword"
|
||||
class="form-control"
|
||||
type="{{ showConfirmPassword ? 'text' : 'password' }}"
|
||||
/>
|
||||
|
||||
<div class="input-group-append">
|
||||
<div class="action-buttons">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
appStopClick
|
||||
appA11yTitle="{{ 'toggleVisibility' | i18n }}"
|
||||
[attr.aria-pressed]="showConfirmPassword"
|
||||
(click)="toggleConfirmPassword()"
|
||||
>
|
||||
<i
|
||||
class="bwi bwi-lg"
|
||||
aria-hidden="true"
|
||||
[ngClass]="{
|
||||
'bwi-eye': !showConfirmPassword,
|
||||
'bwi-eye-slash': showConfirmPassword
|
||||
}"
|
||||
></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-submit"
|
||||
[disabled]="form.loading || disabled"
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
||||
<span>{{ "confirmFormat" | i18n }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-submit"
|
||||
[disabled]="form.loading || exportForm.disabled"
|
||||
>
|
||||
<i class="bwi bwi-spinner bwi-spin" title="{{ 'loading' | i18n }}" aria-hidden="true"></i>
|
||||
<span>{{ "exportVault" | i18n }}</span>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { Component, ViewChild, ViewContainerRef } from "@angular/core";
|
||||
import { FormBuilder, FormControl, FormGroup } from "@angular/forms";
|
||||
|
||||
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/components/export.component";
|
||||
import { ModalConfig, ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
|
||||
import { EventService } from "@bitwarden/common/abstractions/event.service";
|
||||
import { ExportService } from "@bitwarden/common/abstractions/export.service";
|
||||
@@ -9,7 +11,10 @@ import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
|
||||
import { UserVerificationPromptService } from "@bitwarden/common/abstractions/userVerificationPrompt.service";
|
||||
import { EncryptedExportType } from "@bitwarden/common/enums/EncryptedExportType";
|
||||
|
||||
@Component({
|
||||
selector: "app-export",
|
||||
@@ -17,6 +22,11 @@ import { UserVerificationService } from "@bitwarden/common/abstractions/userVeri
|
||||
})
|
||||
export class ExportComponent extends BaseExportComponent {
|
||||
organizationId: string;
|
||||
showPassword: boolean;
|
||||
showConfirmPassword: boolean;
|
||||
confirmDescription: string;
|
||||
confirmButtonText: string;
|
||||
modalTitle: string;
|
||||
|
||||
constructor(
|
||||
cryptoService: CryptoService,
|
||||
@@ -27,7 +37,12 @@ export class ExportComponent extends BaseExportComponent {
|
||||
policyService: PolicyService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
formBuilder: FormBuilder
|
||||
formBuilder: FormBuilder,
|
||||
modalService: ModalService,
|
||||
apiService: ApiService,
|
||||
stateService: StateService,
|
||||
userVerificationPromptService: UserVerificationPromptService,
|
||||
modalConfig: ModalConfig
|
||||
) {
|
||||
super(
|
||||
cryptoService,
|
||||
@@ -39,12 +54,85 @@ export class ExportComponent extends BaseExportComponent {
|
||||
window,
|
||||
logService,
|
||||
userVerificationService,
|
||||
formBuilder
|
||||
formBuilder,
|
||||
modalService,
|
||||
apiService,
|
||||
stateService,
|
||||
userVerificationPromptService,
|
||||
modalConfig
|
||||
);
|
||||
}
|
||||
|
||||
async submit() {
|
||||
const confirmDescription =
|
||||
this.exportForm.get("fileEncryptionType").value == EncryptedExportType.FileEncrypted
|
||||
? "confirmVaultExportDesc"
|
||||
: "encExportKeyWarningDesc";
|
||||
const confirmButtonText = "exportVault";
|
||||
const modalTitle = "confirmVaultExport";
|
||||
|
||||
if (!this.validForm) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (
|
||||
await this.userVerificationPromptService.showUserVerificationPrompt(
|
||||
confirmDescription,
|
||||
confirmButtonText,
|
||||
modalTitle
|
||||
)
|
||||
) {
|
||||
//successful
|
||||
this.submitWithSecretAlreadyVerified();
|
||||
}
|
||||
} catch {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("error"),
|
||||
this.i18nService.t("invalidMasterPassword")
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
togglePassword() {
|
||||
this.exportForm.get("showPassword").setValue(!this.exportForm.get("showPassword").value);
|
||||
document.getElementById("newPassword").focus();
|
||||
}
|
||||
|
||||
toggleConfirmPassword() {
|
||||
this.exportForm
|
||||
.get("showConfirmPassword")
|
||||
.setValue(!this.exportForm.get("showConfirmPassword").value);
|
||||
document.getElementById("newConfirmPassword").focus();
|
||||
}
|
||||
|
||||
protected saved() {
|
||||
super.saved();
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("exportSuccess"));
|
||||
}
|
||||
|
||||
get validForm() {
|
||||
if (
|
||||
this.fileEncryptionType == EncryptedExportType.FileEncrypted &&
|
||||
this.format == "encrypted_json"
|
||||
) {
|
||||
if (this.password.length > 0 || this.confirmPassword.length > 0) {
|
||||
if (this.password != this.confirmPassword) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch")
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
this.encryptionPassword = this.password;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
this.clearPasswordField();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,13 +3,18 @@ import { Router } from "@angular/router";
|
||||
import * as JSZip from "jszip";
|
||||
import Swal, { SweetAlertIcon } from "sweetalert2";
|
||||
|
||||
import { ModalService } from "@bitwarden/angular/services/modal.service";
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { ImportService } from "@bitwarden/common/abstractions/import.service";
|
||||
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
|
||||
import { LogService } from "@bitwarden/common/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { PolicyService } from "@bitwarden/common/abstractions/policy.service";
|
||||
import { ImportOption, ImportType } from "@bitwarden/common/enums/importOptions";
|
||||
import { PolicyType } from "@bitwarden/common/enums/policyType";
|
||||
import { ImportError } from "@bitwarden/common/importers/importError";
|
||||
|
||||
import { FilePasswordPromptComponent } from "../components/file-password-prompt.component";
|
||||
|
||||
@Component({
|
||||
selector: "app-import",
|
||||
@@ -20,9 +25,10 @@ export class ImportComponent implements OnInit {
|
||||
importOptions: ImportOption[];
|
||||
format: ImportType = null;
|
||||
fileContents: string;
|
||||
formPromise: Promise<Error>;
|
||||
formPromise: Promise<ImportError>;
|
||||
loading = false;
|
||||
importBlockedByPolicy = false;
|
||||
protected component = FilePasswordPromptComponent;
|
||||
|
||||
protected organizationId: string = null;
|
||||
protected successNavigate: any[] = ["vault"];
|
||||
@@ -33,7 +39,9 @@ export class ImportComponent implements OnInit {
|
||||
protected router: Router,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected policyService: PolicyService,
|
||||
private logService: LogService
|
||||
private logService: LogService,
|
||||
protected modalService: ModalService,
|
||||
protected keyConnectorService: KeyConnectorService
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -55,7 +63,6 @@ export class ImportComponent implements OnInit {
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
const importer = this.importService.getImporter(this.format, this.organizationId);
|
||||
if (importer === null) {
|
||||
this.platformUtilsService.showToast(
|
||||
@@ -108,10 +115,23 @@ export class ImportComponent implements OnInit {
|
||||
this.formPromise = this.importService.import(importer, fileContents, this.organizationId);
|
||||
const error = await this.formPromise;
|
||||
if (error != null) {
|
||||
this.error(error);
|
||||
this.loading = false;
|
||||
return;
|
||||
//Check if the error is that a password is required
|
||||
if (error.passwordRequired) {
|
||||
if (await this.promptFilePassword(fileContents)) {
|
||||
//successful
|
||||
} else {
|
||||
//failed - File Password issues
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.error(error);
|
||||
this.loading = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//No errors, display success message
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("importSuccess"));
|
||||
this.router.navigate(this.successNavigate);
|
||||
} catch (e) {
|
||||
@@ -121,6 +141,10 @@ export class ImportComponent implements OnInit {
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
private async promptFilePassword(fcontents: string) {
|
||||
return await this.showPasswordPrompt(fcontents, this.organizationId);
|
||||
}
|
||||
|
||||
getFormatInstructionTitle() {
|
||||
if (this.format == null) {
|
||||
return null;
|
||||
@@ -225,4 +249,33 @@ export class ImportComponent implements OnInit {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
protectedFields() {
|
||||
return ["TOTP", "Password", "H_Field", "Card Number", "Security Code"];
|
||||
}
|
||||
|
||||
async showPasswordPrompt(fcontents: string, organizationId: string) {
|
||||
// if (!(await this.enabled())) {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
const ref = this.modalService.open(this.component, {
|
||||
allowMultipleModals: true,
|
||||
data: {
|
||||
fileContents: fcontents,
|
||||
organizationId: organizationId,
|
||||
},
|
||||
});
|
||||
|
||||
// if (ref == null) {
|
||||
// return false;
|
||||
// }
|
||||
|
||||
const result = await ref.onClosedPromise();
|
||||
return result === true;
|
||||
}
|
||||
|
||||
async enabled() {
|
||||
return !this.keyConnectorService.getUsesKeyConnector();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -666,6 +666,9 @@
|
||||
"invalidMasterPassword": {
|
||||
"message": "Invalid master password"
|
||||
},
|
||||
"invalidFilePassword": {
|
||||
"message": "Invalid file password, please use the password you entered when you created the export file."
|
||||
},
|
||||
"lockNow": {
|
||||
"message": "Lock Now"
|
||||
},
|
||||
@@ -878,6 +881,48 @@
|
||||
"fileFormat": {
|
||||
"message": "File Format"
|
||||
},
|
||||
"confirmVaultExportDesc" : {
|
||||
"message": "This file export will be password protected and require the file password to decrypt."
|
||||
},
|
||||
"exportPasswordDescription" : {
|
||||
"message": "This password will be used to export and import this file"
|
||||
},
|
||||
"confirmMasterPassword" : {
|
||||
"message": "Confirm Master Password"
|
||||
},
|
||||
"confirmFormat": {
|
||||
"message": "Confirm Format"
|
||||
},
|
||||
"filePassword": {
|
||||
"message": "File Password"
|
||||
},
|
||||
"confirmFilePassword": {
|
||||
"message": "Confirm File Password"
|
||||
},
|
||||
"accountBackupOptionDescription": {
|
||||
"message": "Leverages your Bitwarden account encryption not master password, to protect the export. This export can only be imported into the current account. Use this to create a backup that cannot be used elsewhere."
|
||||
},
|
||||
"passwordProtectedOptionDescription": {
|
||||
"message": "Create a user-generated password to protect the export. Use this to create an export that can be used in other accounts."
|
||||
},
|
||||
"fileTypeHeading": {
|
||||
"message": "File Type"
|
||||
},
|
||||
"accountBackup": {
|
||||
"message": "Account Backup"
|
||||
},
|
||||
"passwordProtected": {
|
||||
"message": "Password Protected"
|
||||
},
|
||||
"filePasswordAndConfirmFilePasswordDoNotMatch": {
|
||||
"message": "File Password and Confirm File Password do not match."
|
||||
},
|
||||
"confirmVaultImport": {
|
||||
"message": "Confirm Vault Import"
|
||||
},
|
||||
"confirmVaultImportDesc": {
|
||||
"message": "This file is password-protected. Please enter the file password to import data."
|
||||
},
|
||||
"exportSuccess": {
|
||||
"message": "Your vault data has been exported."
|
||||
},
|
||||
|
||||
@@ -6,6 +6,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.modal-footer-content {
|
||||
border: none;
|
||||
border-radius: none;
|
||||
@include themify($themes) {
|
||||
background-color: themed("footerBackgroundColor");
|
||||
}
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
pointer-events: auto;
|
||||
background-clip: padding-box;
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0.3rem;
|
||||
|
||||
10
apps/web/src/services/userVerificationPrompt.service.ts
Normal file
10
apps/web/src/services/userVerificationPrompt.service.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
|
||||
import { UserVerificationPromptService as BaseUserVerificationPrompt } from "@bitwarden/angular/services/userVerificationPrompt.service";
|
||||
|
||||
import { UserVerificationPromptComponent } from "../app/components/user-verification-prompt.component";
|
||||
|
||||
@Injectable()
|
||||
export class UserVerificationPromptService extends BaseUserVerificationPrompt {
|
||||
component = UserVerificationPromptComponent;
|
||||
}
|
||||
Reference in New Issue
Block a user