1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-12 14:23:32 +00:00

[EC-317] Desktop client delete user account (#3151)

* [EC-317] feat: add delete account section in settings

* [EC-317] feat: add new delete account modal

* [EC-317] feat: add ability to replace top-most modal

* [EC-317] chore: remove unecessary lint ignore

* [EC-317] fix: so delete account is closed if export vault is opened

* [EC-317] feat: inital delete account design without i18n

* [EC-317] feat: disabled but basic working delete functionality

* [EC-317] feat: implement according to new design

* [EC-317] feat: use translations

* [EC-317] feat: implement working deletion

* [EC-317] feat: add loading state and error messages

* [EC-317] feat: add menu bar item

* [EC-317] feat: update form to support typed reactive forms

* [EC-317] chore: update translation text after design review

* [EC-317] feat: move deletion logic to service

* [EC-317] refactor: update web deletion

* [EC-317] feat: disable submit if secret is empty

* [EC-317] fix: handle errors in components as well

* [EC-317] fix: use abstraction as interface

* [EC-317] refactor: extract deleteAccount from api service

* [EC-317] fix: typo in translations

* [EC-317] chore: rename to accountApiService
This commit is contained in:
Andreas Coroiu
2022-07-29 21:49:58 +02:00
committed by GitHub
parent cc91b79a15
commit a22ef4d36c
23 changed files with 264 additions and 48 deletions

View File

@@ -5,6 +5,7 @@ import { ControlValueAccessor, UntypedFormControl, NG_VALUE_ACCESSOR } from "@an
import { KeyConnectorService } from "@bitwarden/common/abstractions/keyConnector.service";
import { UserVerificationService } from "@bitwarden/common/abstractions/userVerification.service";
import { VerificationType } from "@bitwarden/common/enums/verificationType";
import { Utils } from "@bitwarden/common/misc/utils";
import { Verification } from "@bitwarden/common/types/verification";
/**
@@ -90,7 +91,7 @@ export class UserVerificationComponent implements ControlValueAccessor, OnInit {
this.onChange({
type: this.usesKeyConnector ? VerificationType.OTP : VerificationType.MasterPassword,
secret: secret,
secret: Utils.isNullOrWhitespace(secret) ? null : secret,
});
}
}

View File

@@ -3,6 +3,8 @@ import { InjectionToken, Injector, LOCALE_ID, NgModule } from "@angular/core";
import { ThemingService } from "@bitwarden/angular/services/theming/theming.service";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { AbstractEncryptService } from "@bitwarden/common/abstractions/abstractEncrypt.service";
import { AccountApiService as AccountApiServiceAbstraction } from "@bitwarden/common/abstractions/account/account-api.service.abstraction";
import { AccountService as AccountServiceAbstraction } from "@bitwarden/common/abstractions/account/account.service.abstraction";
import { ApiService as ApiServiceAbstraction } from "@bitwarden/common/abstractions/api.service";
import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/abstractions/appId.service";
import { AuditService as AuditServiceAbstraction } from "@bitwarden/common/abstractions/audit.service";
@@ -49,6 +51,8 @@ import { VaultTimeoutService as VaultTimeoutServiceAbstraction } from "@bitwarde
import { StateFactory } from "@bitwarden/common/factories/stateFactory";
import { Account } from "@bitwarden/common/models/domain/account";
import { GlobalState } from "@bitwarden/common/models/domain/globalState";
import { AccountApiService } from "@bitwarden/common/services/account/account-api.service";
import { AccountService } from "@bitwarden/common/services/account/account.service";
import { ApiService } from "@bitwarden/common/services/api.service";
import { AppIdService } from "@bitwarden/common/services/appId.service";
import { AuditService } from "@bitwarden/common/services/audit.service";
@@ -234,6 +238,21 @@ export const LOG_MAC_FAILURES = new InjectionToken<string>("LOG_MAC_FAILURES");
useClass: FolderApiService,
deps: [FolderServiceAbstraction, ApiServiceAbstraction],
},
{
provide: AccountApiServiceAbstraction,
useClass: AccountApiService,
deps: [ApiServiceAbstraction],
},
{
provide: AccountServiceAbstraction,
useClass: AccountService,
deps: [
AccountApiServiceAbstraction,
UserVerificationServiceAbstraction,
MessagingServiceAbstraction,
LogService,
],
},
{ provide: LogService, useFactory: () => new ConsoleLogService(false) },
{
provide: CollectionServiceAbstraction,

View File

@@ -17,7 +17,8 @@ import { ModalRef } from "../components/modal/modal.ref";
export class ModalConfig<D = any> {
data?: D;
allowMultipleModals = false;
allowMultipleModals?: boolean;
replaceTopModal?: boolean;
}
@Injectable()
@@ -63,13 +64,18 @@ export class ModalService {
return [modalRef, modalComponentRef.instance.componentRef.instance];
}
open(componentType: Type<any>, config?: ModalConfig) {
if (!(config?.allowMultipleModals ?? false) && this.modalCount > 0) {
open(componentType: Type<any>, config: ModalConfig = {}) {
const { replaceTopModal = false, allowMultipleModals = false } = config;
if (this.modalCount > 0 && replaceTopModal) {
this.topModal.instance.close();
}
if (this.modalCount > 0 && !allowMultipleModals) {
return;
}
// eslint-disable-next-line
const [modalRef, _] = this.openInternal(componentType, config, true);
const [modalRef] = this.openInternal(componentType, config, true);
return modalRef;
}
@@ -89,6 +95,10 @@ export class ModalService {
return this.componentFactoryResolver.resolveComponentFactory(componentType);
}
closeAll(): void {
this.modalList.forEach((modal) => modal.instance.close());
}
protected openInternal(
componentType: Type<any>,
config?: ModalConfig,