mirror of
https://github.com/bitwarden/browser.git
synced 2025-01-07 19:07:45 +01:00
Merge branch 'main' into autofill/pm-5189-fix-issues-present-with-inline-menu-rendering-in-iframes
This commit is contained in:
commit
6e56f23e44
10
angular.json
10
angular.json
@ -160,7 +160,15 @@
|
||||
"configDir": ".storybook",
|
||||
"browserTarget": "components:build",
|
||||
"compodoc": true,
|
||||
"compodocArgs": ["-e", "json", "-d", "."],
|
||||
"compodocArgs": [
|
||||
"-p",
|
||||
"./tsconfig.json",
|
||||
"-e",
|
||||
"json",
|
||||
"-d",
|
||||
".",
|
||||
"--disableRoutesGraph"
|
||||
],
|
||||
"outputDir": "storybook-static"
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/ge
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { AddEditCipherInfo } from "@bitwarden/common/vault/types/add-edit-cipher-info";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-generator",
|
||||
@ -34,6 +35,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
logService: LogService,
|
||||
ngZone: NgZone,
|
||||
private location: Location,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
passwordGenerationService,
|
||||
@ -45,6 +47,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
route,
|
||||
ngZone,
|
||||
window,
|
||||
toastService,
|
||||
);
|
||||
this.cipherService = cipherService;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryCompon
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-password-generator-history",
|
||||
@ -16,8 +17,9 @@ export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHist
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService,
|
||||
private location: Location,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window);
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window, toastService);
|
||||
}
|
||||
|
||||
close() {
|
||||
|
@ -15,7 +15,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
|
||||
import { BrowserStateService } from "../../../platform/services/abstractions/browser-state.service";
|
||||
@ -53,6 +53,7 @@ export class SendAddEditComponent extends BaseAddEditComponent {
|
||||
private filePopoutUtilsService: FilePopoutUtilsService,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
accountService: AccountService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@ -69,6 +70,7 @@ export class SendAddEditComponent extends BaseAddEditComponent {
|
||||
formBuilder,
|
||||
billingAccountProfileStateService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { BrowserSendComponentState } from "../../../models/browserSendComponentState";
|
||||
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
|
||||
@ -49,6 +49,7 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
||||
logService: LogService,
|
||||
sendApiService: SendApiService,
|
||||
dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
sendService,
|
||||
@ -61,6 +62,7 @@ export class SendGroupingsComponent extends BaseSendComponent {
|
||||
logService,
|
||||
sendApiService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
super.onSuccessfulLoad = async () => {
|
||||
this.selectAll();
|
||||
|
@ -15,7 +15,7 @@ import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { BrowserComponentState } from "../../../models/browserComponentState";
|
||||
import BrowserPopupUtils from "../../../platform/popup/browser-popup-utils";
|
||||
@ -51,6 +51,7 @@ export class SendTypeComponent extends BaseSendComponent {
|
||||
logService: LogService,
|
||||
sendApiService: SendApiService,
|
||||
dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
sendService,
|
||||
@ -63,6 +64,7 @@ export class SendTypeComponent extends BaseSendComponent {
|
||||
logService,
|
||||
sendApiService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
super.onSuccessfulLoad = async () => {
|
||||
this.selectType(this.type);
|
||||
|
@ -11,6 +11,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/username";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { GeneratorComponent } from "./generator.component";
|
||||
|
||||
@ -59,6 +60,10 @@ describe("GeneratorComponent", () => {
|
||||
provide: AccountService,
|
||||
useValue: mock<AccountService>(),
|
||||
},
|
||||
{
|
||||
provide: ToastService,
|
||||
useValue: mock<ToastService>(),
|
||||
},
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA],
|
||||
}).compileComponents();
|
||||
|
@ -8,6 +8,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/username";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-generator",
|
||||
@ -23,6 +24,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
route: ActivatedRoute,
|
||||
ngZone: NgZone,
|
||||
logService: LogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
passwordGenerationService,
|
||||
@ -34,6 +36,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
route,
|
||||
ngZone,
|
||||
window,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@ import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryCompon
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-password-generator-history",
|
||||
@ -14,7 +15,8 @@ export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHist
|
||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window);
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window, toastService);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-add-edit",
|
||||
@ -36,6 +36,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
formBuilder: FormBuilder,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
accountService: AccountService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@ -52,6 +53,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
formBuilder,
|
||||
billingAccountProfileStateService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
@ -70,11 +72,11 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
super.copyLinkToClipboard(link);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("valueCopied", this.i18nService.t("sendLink")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("valueCopied", this.i18nService.t("sendLink")),
|
||||
});
|
||||
}
|
||||
|
||||
async resetAndLoad() {
|
||||
|
@ -11,7 +11,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { invokeMenu, RendererMenuItem } from "../../../utils";
|
||||
import { SearchBarService } from "../../layout/search/search-bar.service";
|
||||
@ -49,6 +49,7 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro
|
||||
logService: LogService,
|
||||
sendApiService: SendApiService,
|
||||
dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
sendService,
|
||||
@ -61,6 +62,7 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro
|
||||
logService,
|
||||
sendApiService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
this.searchBarService.searchText$.subscribe((searchText) => {
|
||||
|
@ -1,32 +0,0 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
import { map, Observable, shareReplay, startWith, switchMap } from "rxjs";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
|
||||
@Component({
|
||||
selector: "app-org-reporting",
|
||||
templateUrl: "reporting.component.html",
|
||||
})
|
||||
export class ReportingComponent implements OnInit {
|
||||
organization$: Observable<Organization>;
|
||||
showLeftNav$: Observable<boolean>;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private organizationService: OrganizationService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.organization$ = this.route.params.pipe(
|
||||
switchMap((params) => this.organizationService.get$(params.organizationId)),
|
||||
shareReplay({ refCount: true, bufferSize: 1 }),
|
||||
);
|
||||
|
||||
this.showLeftNav$ = this.organization$.pipe(
|
||||
map((o) => o.canAccessEventLogs && o.canAccessReports),
|
||||
startWith(true),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { OrganizationService } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-org-tools",
|
||||
templateUrl: "tools.component.html",
|
||||
})
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class ToolsComponent {
|
||||
organization: Organization;
|
||||
accessReports = false;
|
||||
loading = true;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private organizationService: OrganizationService,
|
||||
private messagingService: MessagingService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
this.route.parent.params.subscribe(async (params) => {
|
||||
this.organization = await this.organizationService.get(params.organizationId);
|
||||
// TODO: Maybe we want to just make sure they are not on a free plan? Just compare useTotp for now
|
||||
// since all paid plans include useTotp
|
||||
this.accessReports = this.organization.useTotp;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
|
||||
upgradeOrganization() {
|
||||
this.messagingService.send("upgradeOrganization", { organizationId: this.organization.id });
|
||||
}
|
||||
}
|
@ -9,8 +9,7 @@ import { EventType } from "@bitwarden/common/enums";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
||||
|
||||
import { ExportComponent } from "../../../../tools/vault-export/export.component";
|
||||
@ -23,7 +22,7 @@ import { ExportComponent } from "../../../../tools/vault-export/export.component
|
||||
export class OrganizationVaultExportComponent extends ExportComponent {
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
toastService: ToastService,
|
||||
exportService: VaultExportServiceAbstraction,
|
||||
eventCollectionService: EventCollectionService,
|
||||
private route: ActivatedRoute,
|
||||
@ -36,7 +35,7 @@ export class OrganizationVaultExportComponent extends ExportComponent {
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
toastService,
|
||||
exportService,
|
||||
eventCollectionService,
|
||||
policyService,
|
||||
|
@ -1,44 +1,23 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
|
||||
<div class="row justify-content-md-center mt-5">
|
||||
<div class="col-5">
|
||||
<p class="lead text-center mb-4">{{ "passwordHint" | i18n }}</p>
|
||||
<div class="card d-block">
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="email">{{ "emailAddress" | i18n }}</label>
|
||||
<input
|
||||
id="email"
|
||||
class="form-control"
|
||||
type="text"
|
||||
name="Email"
|
||||
[(ngModel)]="email"
|
||||
required
|
||||
appAutofocus
|
||||
inputmode="email"
|
||||
appInputVerbatim="false"
|
||||
/>
|
||||
<small class="form-text text-muted">{{ "enterEmailToGetHint" | i18n }}</small>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-primary btn-block btn-submit"
|
||||
[disabled]="form.loading"
|
||||
>
|
||||
<span [hidden]="form.loading">{{ "submit" | i18n }}</span>
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn btn-outline-secondary btn-block ml-2 mt-0">
|
||||
{{ "cancel" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<bit-form-field>
|
||||
<bit-label>{{ "emailAddress" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
appAutofocus
|
||||
inputmode="email"
|
||||
appInputVerbatim="false"
|
||||
type="email"
|
||||
formControlName="email"
|
||||
/>
|
||||
<bit-hint>{{ "enterEmailToGetHint" | i18n }}</bit-hint>
|
||||
</bit-form-field>
|
||||
<hr />
|
||||
<div class="tw-flex tw-gap-2">
|
||||
<button type="submit" bitButton bitFormButton buttonType="primary" [block]="true">
|
||||
{{ "submit" | i18n }}
|
||||
</button>
|
||||
<a bitButton buttonType="secondary" routerLink="/login" [block]="true">
|
||||
{{ "cancel" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { Router } from "@angular/router";
|
||||
|
||||
import { HintComponent as BaseHintComponent } from "@bitwarden/angular/auth/components/hint.component";
|
||||
@ -13,6 +14,14 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
templateUrl: "hint.component.html",
|
||||
})
|
||||
export class HintComponent extends BaseHintComponent {
|
||||
formGroup = this.formBuilder.group({
|
||||
email: ["", [Validators.email, Validators.required]],
|
||||
});
|
||||
|
||||
get emailFormControl() {
|
||||
return this.formGroup.controls.email;
|
||||
}
|
||||
|
||||
constructor(
|
||||
router: Router,
|
||||
i18nService: I18nService,
|
||||
@ -20,7 +29,24 @@ export class HintComponent extends BaseHintComponent {
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
logService: LogService,
|
||||
loginEmailService: LoginEmailServiceAbstraction,
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
super(router, i18nService, apiService, platformUtilsService, logService, loginEmailService);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
super.ngOnInit();
|
||||
this.emailFormControl.setValue(this.email);
|
||||
}
|
||||
|
||||
// Wrapper method to call super.submit() since properties (e.g., submit) cannot use super directly
|
||||
// This is because properties are assigned per type and generally don't have access to the prototype
|
||||
async superSubmit() {
|
||||
await super.submit();
|
||||
}
|
||||
|
||||
submit = async () => {
|
||||
this.email = this.emailFormControl.value;
|
||||
await this.superSubmit();
|
||||
};
|
||||
}
|
||||
|
@ -1,117 +1,110 @@
|
||||
<div class="tabbed-header">
|
||||
<h1>{{ "encKeySettings" | i18n }}</h1>
|
||||
</div>
|
||||
<h2 bitTypography="h2">{{ "encKeySettings" | i18n }}</h2>
|
||||
<bit-callout type="warning">{{ "kdfSettingsChangeLogoutWarning" | i18n }}</bit-callout>
|
||||
<form #form ngNativeValidate autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-6">
|
||||
<div class="form-group mb-0">
|
||||
<label for="kdf">{{ "kdfAlgorithm" | i18n }}</label>
|
||||
<a
|
||||
class="ml-auto"
|
||||
href="https://bitwarden.com/help/kdf-algorithms"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
<select
|
||||
id="kdf"
|
||||
name="Kdf"
|
||||
[(ngModel)]="kdfConfig.kdfType"
|
||||
(ngModelChange)="onChangeKdf($event)"
|
||||
class="form-control mb-3"
|
||||
required
|
||||
>
|
||||
<option *ngFor="let o of kdfOptions" [ngValue]="o.value">{{ o.name }}</option>
|
||||
</select>
|
||||
<ng-container *ngIf="isArgon2(kdfConfig)">
|
||||
<label for="kdfMemory">{{ "kdfMemory" | i18n }}</label>
|
||||
<input
|
||||
id="kdfMemory"
|
||||
type="number"
|
||||
[min]="ARGON2_MEMORY.min"
|
||||
[max]="ARGON2_MEMORY.max"
|
||||
name="Memory"
|
||||
class="form-control mb-3"
|
||||
[(ngModel)]="kdfConfig.memory"
|
||||
required
|
||||
/>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-group mb-0">
|
||||
<ng-container *ngIf="isPBKDF2(kdfConfig)">
|
||||
<label for="kdfIterations">{{ "kdfIterations" | i18n }}</label>
|
||||
<p bitTypography="body1">
|
||||
{{ "higherKDFIterations" | i18n }}
|
||||
</p>
|
||||
<p bitTypography="body1">
|
||||
{{
|
||||
"kdfToHighWarningIncreaseInIncrements"
|
||||
| i18n: (isPBKDF2(kdfConfig) ? ("incrementsOf100,000" | i18n) : ("smallIncrements" | i18n))
|
||||
}}
|
||||
</p>
|
||||
<form [formGroup]="formGroup" autocomplete="off">
|
||||
<div class="tw-grid tw-grid-cols-12 tw-gap-4">
|
||||
<div class="tw-col-span-6">
|
||||
<bit-form-field>
|
||||
<bit-label
|
||||
>{{ "kdfAlgorithm" | i18n }}
|
||||
<a
|
||||
class="ml-auto"
|
||||
href="https://bitwarden.com/help/what-encryption-is-used/#changing-kdf-iterations"
|
||||
class="tw-ml-auto"
|
||||
bitLink
|
||||
href="https://bitwarden.com/help/kdf-algorithms"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-label>
|
||||
<bit-select formControlName="kdf">
|
||||
<bit-option
|
||||
*ngFor="let option of kdfOptions"
|
||||
[value]="option.value"
|
||||
[label]="option.name"
|
||||
></bit-option>
|
||||
</bit-select>
|
||||
</bit-form-field>
|
||||
<bit-form-field formGroupName="kdfConfig" *ngIf="isArgon2(kdfConfig)">
|
||||
<bit-label>{{ "kdfMemory" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
formControlName="memory"
|
||||
type="number"
|
||||
[min]="ARGON2_MEMORY.min"
|
||||
[max]="ARGON2_MEMORY.max"
|
||||
/>
|
||||
</bit-form-field>
|
||||
</div>
|
||||
<div class="tw-col-span-6">
|
||||
<div class="tw-mb-0">
|
||||
<bit-form-field formGroupName="kdfConfig" *ngIf="isPBKDF2(kdfConfig)">
|
||||
<bit-label>
|
||||
{{ "kdfIterations" | i18n }}
|
||||
<a
|
||||
bitLink
|
||||
class="tw-ml-auto"
|
||||
href="https://bitwarden.com/help/what-encryption-is-used/#changing-kdf-iterations"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</bit-label>
|
||||
<input
|
||||
id="kdfIterations"
|
||||
bitInput
|
||||
type="number"
|
||||
formControlName="iterations"
|
||||
[min]="PBKDF2_ITERATIONS.min"
|
||||
[max]="PBKDF2_ITERATIONS.max"
|
||||
name="KdfIterations"
|
||||
class="form-control"
|
||||
[(ngModel)]="kdfConfig.iterations"
|
||||
required
|
||||
/>
|
||||
</ng-container>
|
||||
<bit-hint>{{ "kdfIterationRecommends" | i18n }}</bit-hint>
|
||||
</bit-form-field>
|
||||
<ng-container *ngIf="isArgon2(kdfConfig)">
|
||||
<label for="kdfIterations">{{ "kdfIterations" | i18n }}</label>
|
||||
<input
|
||||
id="iterations"
|
||||
type="number"
|
||||
[min]="ARGON2_ITERATIONS.min"
|
||||
[max]="ARGON2_ITERATIONS.max"
|
||||
name="Iterations"
|
||||
class="form-control mb-3"
|
||||
[(ngModel)]="kdfConfig.iterations"
|
||||
required
|
||||
/>
|
||||
<label for="kdfParallelism">{{ "kdfParallelism" | i18n }}</label>
|
||||
<input
|
||||
id="kdfParallelism"
|
||||
type="number"
|
||||
[min]="ARGON2_PARALLELISM.min"
|
||||
[max]="ARGON2_PARALLELISM.max"
|
||||
name="Parallelism"
|
||||
class="form-control"
|
||||
[(ngModel)]="kdfConfig.parallelism"
|
||||
required
|
||||
/>
|
||||
<bit-form-field formGroupName="kdfConfig">
|
||||
<bit-label>
|
||||
{{ "kdfIterations" | i18n }}
|
||||
</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
type="number"
|
||||
formControlName="iterations"
|
||||
[min]="ARGON2_ITERATIONS.min"
|
||||
[max]="ARGON2_ITERATIONS.max"
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field formGroupName="kdfConfig">
|
||||
<bit-label>
|
||||
{{ "kdfParallelism" | i18n }}
|
||||
</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
type="number"
|
||||
formControlName="parallelism"
|
||||
[min]="ARGON2_PARALLELISM.min"
|
||||
[max]="ARGON2_PARALLELISM.max"
|
||||
/>
|
||||
</bit-form-field>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<ng-container *ngIf="isPBKDF2(kdfConfig)">
|
||||
<p class="small form-text text-muted">
|
||||
{{ "kdfIterationsDesc" | i18n: (PBKDF2_ITERATIONS.defaultValue | number) }}
|
||||
</p>
|
||||
<bit-callout type="warning">
|
||||
{{ "kdfIterationsWarning" | i18n: (100000 | number) }}
|
||||
</bit-callout>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="isArgon2(kdfConfig)">
|
||||
<p class="small form-text text-muted">{{ "argon2Desc" | i18n }}</p>
|
||||
<bit-callout type="warning"> {{ "argon2Warning" | i18n }}</bit-callout>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
(click)="openConfirmationModal()"
|
||||
type="button"
|
||||
buttonType="primary"
|
||||
bitButton
|
||||
[loading]="form.loading"
|
||||
bitFormButton
|
||||
>
|
||||
{{ "changeKdf" | i18n }}
|
||||
</button>
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder, FormControl, ValidatorFn, Validators } from "@angular/forms";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { KdfConfigService } from "@bitwarden/common/auth/abstractions/kdf-config.service";
|
||||
import {
|
||||
@ -24,8 +26,34 @@ import { ChangeKdfConfirmationComponent } from "./change-kdf-confirmation.compon
|
||||
})
|
||||
export class ChangeKdfComponent implements OnInit {
|
||||
kdfConfig: KdfConfig = DEFAULT_KDF_CONFIG;
|
||||
kdfType = KdfType;
|
||||
kdfOptions: any[] = [];
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
protected formGroup = this.formBuilder.group({
|
||||
kdf: new FormControl(KdfType.PBKDF2_SHA256, [Validators.required]),
|
||||
kdfConfig: this.formBuilder.group({
|
||||
iterations: [
|
||||
this.kdfConfig.iterations,
|
||||
[
|
||||
Validators.required,
|
||||
Validators.min(PBKDF2_ITERATIONS.min),
|
||||
Validators.max(PBKDF2_ITERATIONS.max),
|
||||
],
|
||||
],
|
||||
memory: [
|
||||
null as number,
|
||||
[Validators.required, Validators.min(ARGON2_MEMORY.min), Validators.max(ARGON2_MEMORY.max)],
|
||||
],
|
||||
parallelism: [
|
||||
null as number,
|
||||
[
|
||||
Validators.required,
|
||||
Validators.min(ARGON2_PARALLELISM.min),
|
||||
Validators.max(ARGON2_PARALLELISM.max),
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
// Default values for template
|
||||
protected PBKDF2_ITERATIONS = PBKDF2_ITERATIONS;
|
||||
@ -36,6 +64,7 @@ export class ChangeKdfComponent implements OnInit {
|
||||
constructor(
|
||||
private dialogService: DialogService,
|
||||
private kdfConfigService: KdfConfigService,
|
||||
private formBuilder: FormBuilder,
|
||||
) {
|
||||
this.kdfOptions = [
|
||||
{ name: "PBKDF2 SHA-256", value: KdfType.PBKDF2_SHA256 },
|
||||
@ -45,6 +74,86 @@ export class ChangeKdfComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this.kdfConfig = await this.kdfConfigService.getKdfConfig();
|
||||
this.formGroup.get("kdf").setValue(this.kdfConfig.kdfType, { emitEvent: false });
|
||||
this.setFormControlValues(this.kdfConfig);
|
||||
|
||||
this.formGroup
|
||||
.get("kdf")
|
||||
.valueChanges.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((newValue) => {
|
||||
this.updateKdfConfig(newValue);
|
||||
});
|
||||
}
|
||||
private updateKdfConfig(newValue: KdfType) {
|
||||
let config: KdfConfig;
|
||||
const validators: { [key: string]: ValidatorFn[] } = {
|
||||
iterations: [],
|
||||
memory: [],
|
||||
parallelism: [],
|
||||
};
|
||||
|
||||
switch (newValue) {
|
||||
case KdfType.PBKDF2_SHA256:
|
||||
config = new PBKDF2KdfConfig();
|
||||
validators.iterations = [
|
||||
Validators.required,
|
||||
Validators.min(PBKDF2_ITERATIONS.min),
|
||||
Validators.max(PBKDF2_ITERATIONS.max),
|
||||
];
|
||||
break;
|
||||
case KdfType.Argon2id:
|
||||
config = new Argon2KdfConfig();
|
||||
validators.iterations = [
|
||||
Validators.required,
|
||||
Validators.min(ARGON2_ITERATIONS.min),
|
||||
Validators.max(ARGON2_ITERATIONS.max),
|
||||
];
|
||||
validators.memory = [
|
||||
Validators.required,
|
||||
Validators.min(ARGON2_MEMORY.min),
|
||||
Validators.max(ARGON2_MEMORY.max),
|
||||
];
|
||||
validators.parallelism = [
|
||||
Validators.required,
|
||||
Validators.min(ARGON2_PARALLELISM.min),
|
||||
Validators.max(ARGON2_PARALLELISM.max),
|
||||
];
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown KDF type.");
|
||||
}
|
||||
|
||||
this.kdfConfig = config;
|
||||
this.setFormValidators(validators);
|
||||
this.setFormControlValues(this.kdfConfig);
|
||||
}
|
||||
|
||||
private setFormValidators(validators: { [key: string]: ValidatorFn[] }) {
|
||||
this.setValidators("kdfConfig.iterations", validators.iterations);
|
||||
this.setValidators("kdfConfig.memory", validators.memory);
|
||||
this.setValidators("kdfConfig.parallelism", validators.parallelism);
|
||||
}
|
||||
private setValidators(controlName: string, validators: ValidatorFn[]) {
|
||||
const control = this.formGroup.get(controlName);
|
||||
if (control) {
|
||||
control.setValidators(validators);
|
||||
control.updateValueAndValidity();
|
||||
}
|
||||
}
|
||||
private setFormControlValues(kdfConfig: KdfConfig) {
|
||||
this.formGroup.get("kdfConfig").reset();
|
||||
if (kdfConfig.kdfType === KdfType.PBKDF2_SHA256) {
|
||||
this.formGroup.get("kdfConfig.iterations").setValue(kdfConfig.iterations);
|
||||
} else if (kdfConfig.kdfType === KdfType.Argon2id) {
|
||||
this.formGroup.get("kdfConfig.iterations").setValue(kdfConfig.iterations);
|
||||
this.formGroup.get("kdfConfig.memory").setValue(kdfConfig.memory);
|
||||
this.formGroup.get("kdfConfig.parallelism").setValue(kdfConfig.parallelism);
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
|
||||
isPBKDF2(t: KdfConfig): t is PBKDF2KdfConfig {
|
||||
@ -55,17 +164,18 @@ export class ChangeKdfComponent implements OnInit {
|
||||
return t instanceof Argon2KdfConfig;
|
||||
}
|
||||
|
||||
async onChangeKdf(newValue: KdfType) {
|
||||
if (newValue === KdfType.PBKDF2_SHA256) {
|
||||
this.kdfConfig = new PBKDF2KdfConfig();
|
||||
} else if (newValue === KdfType.Argon2id) {
|
||||
this.kdfConfig = new Argon2KdfConfig();
|
||||
} else {
|
||||
throw new Error("Unknown KDF type.");
|
||||
}
|
||||
}
|
||||
|
||||
async openConfirmationModal() {
|
||||
this.formGroup.markAllAsTouched();
|
||||
if (this.formGroup.invalid) {
|
||||
return;
|
||||
}
|
||||
if (this.kdfConfig.kdfType === KdfType.PBKDF2_SHA256) {
|
||||
this.kdfConfig.iterations = this.formGroup.get("kdfConfig.iterations").value;
|
||||
} else if (this.kdfConfig.kdfType === KdfType.Argon2id) {
|
||||
this.kdfConfig.iterations = this.formGroup.get("kdfConfig.iterations").value;
|
||||
this.kdfConfig.memory = this.formGroup.get("kdfConfig.memory").value;
|
||||
this.kdfConfig.parallelism = this.formGroup.get("kdfConfig.parallelism").value;
|
||||
}
|
||||
this.dialogService.open(ChangeKdfConfirmationComponent, {
|
||||
data: {
|
||||
kdfConfig: this.kdfConfig,
|
||||
|
@ -1,34 +1,16 @@
|
||||
<form #form (ngSubmit)="submit()" [appApiAction]="formPromise" class="container" ngNativeValidate>
|
||||
<div class="row justify-content-md-center mt-5">
|
||||
<div class="col-5">
|
||||
<p class="lead text-center mb-4">{{ "deleteAccount" | i18n }}</p>
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<app-callout type="warning">{{ "deleteAccountWarning" | i18n }}</app-callout>
|
||||
<p class="text-center">
|
||||
<strong>{{ email }}</strong>
|
||||
</p>
|
||||
<p>{{ "deleteRecoverConfirmDesc" | i18n }}</p>
|
||||
<hr />
|
||||
<div class="d-flex">
|
||||
<button
|
||||
type="submit"
|
||||
class="btn btn-danger btn-block btn-submit"
|
||||
[disabled]="form.loading"
|
||||
>
|
||||
<span>{{ "deleteAccount" | i18n }}</span>
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</button>
|
||||
<a routerLink="/login" class="btn btn-outline-secondary btn-block ml-2 mt-0">
|
||||
{{ "cancel" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<form [bitSubmit]="submit" [formGroup]="formGroup">
|
||||
<app-callout type="warning">{{ "deleteAccountWarning" | i18n }}</app-callout>
|
||||
<p bitTypography="body1" class="tw-text-center">
|
||||
<strong>{{ email }}</strong>
|
||||
</p>
|
||||
<p bitTypography="body1">{{ "deleteRecoverConfirmDesc" | i18n }}</p>
|
||||
<hr />
|
||||
<div class="tw-flex tw-gap-2">
|
||||
<button type="submit" bitButton bitFormButton buttonType="danger" [block]="true">
|
||||
{{ "deleteAccount" | i18n }}
|
||||
</button>
|
||||
<a bitButton buttonType="secondary" routerLink="/login" [block]="true">
|
||||
{{ "cancel" | i18n }}
|
||||
</a>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { FormGroup } from "@angular/forms";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { first } from "rxjs/operators";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { VerifyDeleteRecoverRequest } from "@bitwarden/common/models/request/verify-delete-recover.request";
|
||||
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";
|
||||
|
||||
@Component({
|
||||
@ -15,10 +15,10 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class VerifyRecoverDeleteComponent implements OnInit {
|
||||
email: string;
|
||||
formPromise: Promise<any>;
|
||||
|
||||
private userId: string;
|
||||
private token: string;
|
||||
protected formGroup = new FormGroup({});
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
@ -26,7 +26,6 @@ export class VerifyRecoverDeleteComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private route: ActivatedRoute,
|
||||
private logService: LogService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@ -37,28 +36,19 @@ export class VerifyRecoverDeleteComponent implements OnInit {
|
||||
this.token = qParams.token;
|
||||
this.email = qParams.email;
|
||||
} else {
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.router.navigate(["/"]);
|
||||
await this.router.navigate(["/"]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async submit() {
|
||||
try {
|
||||
const request = new VerifyDeleteRecoverRequest(this.userId, this.token);
|
||||
this.formPromise = this.apiService.postAccountRecoverDeleteToken(request);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("accountDeleted"),
|
||||
this.i18nService.t("accountDeletedDesc"),
|
||||
);
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this.router.navigate(["/"]);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
submit = async () => {
|
||||
const request = new VerifyDeleteRecoverRequest(this.userId, this.token);
|
||||
await this.apiService.postAccountRecoverDeleteToken(request);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("accountDeleted"),
|
||||
this.i18nService.t("accountDeletedDesc"),
|
||||
);
|
||||
await this.router.navigate(["/"]);
|
||||
};
|
||||
}
|
||||
|
@ -111,12 +111,6 @@ const routes: Routes = [
|
||||
component: SetPasswordComponent,
|
||||
data: { titleId: "setMasterPassword" } satisfies DataProperties,
|
||||
},
|
||||
{
|
||||
path: "hint",
|
||||
component: HintComponent,
|
||||
canActivate: [UnauthGuard],
|
||||
data: { titleId: "passwordHint" } satisfies DataProperties,
|
||||
},
|
||||
{
|
||||
path: "lock",
|
||||
component: LockComponent,
|
||||
@ -136,12 +130,6 @@ const routes: Routes = [
|
||||
data: { titleId: "acceptFamilySponsorship", doNotSaveUrl: false } satisfies DataProperties,
|
||||
},
|
||||
{ path: "recover", pathMatch: "full", redirectTo: "recover-2fa" },
|
||||
{
|
||||
path: "verify-recover-delete",
|
||||
component: VerifyRecoverDeleteComponent,
|
||||
canActivate: [UnauthGuard],
|
||||
data: { titleId: "deleteAccount" } satisfies DataProperties,
|
||||
},
|
||||
{
|
||||
path: "verify-recover-delete-org",
|
||||
component: VerifyRecoverDeleteOrgComponent,
|
||||
@ -330,6 +318,39 @@ const routes: Routes = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "verify-recover-delete",
|
||||
canActivate: [unauthGuardFn()],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: VerifyRecoverDeleteComponent,
|
||||
data: {
|
||||
pageTitle: "deleteAccount",
|
||||
titleId: "deleteAccount",
|
||||
} satisfies DataProperties & AnonLayoutWrapperData,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "hint",
|
||||
canActivate: [unauthGuardFn()],
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: HintComponent,
|
||||
data: {
|
||||
pageTitle: "passwordHint",
|
||||
titleId: "passwordHint",
|
||||
} satisfies DataProperties & AnonLayoutWrapperData,
|
||||
},
|
||||
{
|
||||
path: "",
|
||||
component: EnvironmentSelectorComponent,
|
||||
outlet: "environment-selector",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "remove-password",
|
||||
component: RemovePasswordComponent,
|
||||
|
@ -8,7 +8,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { UsernameGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/username";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { PasswordGeneratorHistoryComponent } from "./password-generator-history.component";
|
||||
|
||||
@ -27,6 +27,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
route: ActivatedRoute,
|
||||
ngZone: NgZone,
|
||||
private dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
passwordGenerationService,
|
||||
@ -38,6 +39,7 @@ export class GeneratorComponent extends BaseGeneratorComponent {
|
||||
route,
|
||||
ngZone,
|
||||
window,
|
||||
toastService,
|
||||
);
|
||||
if (platformUtilsService.isSelfHost()) {
|
||||
// Allow only valid email forwarders for self host
|
||||
|
@ -4,6 +4,7 @@ import { PasswordGeneratorHistoryComponent as BasePasswordGeneratorHistoryCompon
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/common/tools/generator/password";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-password-generator-history",
|
||||
@ -14,7 +15,8 @@ export class PasswordGeneratorHistoryComponent extends BasePasswordGeneratorHist
|
||||
passwordGenerationService: PasswordGenerationServiceAbstraction,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window);
|
||||
super(passwordGenerationService, platformUtilsService, i18nService, window, toastService);
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
||||
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
@ -18,7 +17,7 @@ import { SendAccessResponse } from "@bitwarden/common/tools/send/models/response
|
||||
import { SendAccessView } from "@bitwarden/common/tools/send/models/view/send-access.view";
|
||||
import { SEND_KDF_ITERATIONS } from "@bitwarden/common/tools/send/send-kdf";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { NoItemsModule } from "@bitwarden/components";
|
||||
import { NoItemsModule, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
@ -67,7 +66,7 @@ export class AccessComponent implements OnInit {
|
||||
private route: ActivatedRoute,
|
||||
private cryptoService: CryptoService,
|
||||
private sendApiService: SendApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
private i18nService: I18nService,
|
||||
private configService: ConfigService,
|
||||
protected formBuilder: FormBuilder,
|
||||
@ -142,11 +141,11 @@ export class AccessComponent implements OnInit {
|
||||
} else if (e.statusCode === 404) {
|
||||
this.unavailable = true;
|
||||
} else if (e.statusCode === 400) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
e.message,
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: e.message,
|
||||
});
|
||||
} else {
|
||||
this.error = true;
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-add-edit",
|
||||
@ -42,6 +42,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
protected dialogRef: DialogRef,
|
||||
@Inject(DIALOG_DATA) params: { sendId: string },
|
||||
accountService: AccountService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@ -58,6 +59,7 @@ export class AddEditComponent extends BaseAddEditComponent {
|
||||
formBuilder,
|
||||
billingAccountProfileStateService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
|
||||
this.sendId = params.sendId;
|
||||
|
@ -3,13 +3,13 @@ import { Component, Input } from "@angular/core";
|
||||
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncArrayBuffer } from "@bitwarden/common/platform/models/domain/enc-array-buffer";
|
||||
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
|
||||
import { SendAccessRequest } from "@bitwarden/common/tools/send/models/request/send-access.request";
|
||||
import { SendAccessView } from "@bitwarden/common/tools/send/models/view/send-access.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
@ -25,7 +25,7 @@ export class SendAccessFileComponent {
|
||||
@Input() accessRequest: SendAccessRequest;
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private toastService: ToastService,
|
||||
private cryptoService: CryptoService,
|
||||
private fileDownloadService: FileDownloadService,
|
||||
private sendApiService: SendApiService,
|
||||
@ -42,13 +42,21 @@ export class SendAccessFileComponent {
|
||||
);
|
||||
|
||||
if (Utils.isNullOrWhitespace(downloadData.url)) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("missingSendFile"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("missingSendFile"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await fetch(new Request(downloadData.url, { cache: "no-store" }));
|
||||
if (response.status !== 200) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("errorOccurred"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -61,7 +69,11 @@ export class SendAccessFileComponent {
|
||||
downloadMethod: "save",
|
||||
});
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("errorOccurred"),
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import { FormBuilder } from "@angular/forms";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SendAccessView } from "@bitwarden/common/tools/send/models/view/send-access.view";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
@ -25,6 +26,7 @@ export class SendAccessTextComponent {
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
get send(): SendAccessView {
|
||||
@ -46,11 +48,11 @@ export class SendAccessTextComponent {
|
||||
|
||||
protected copyText() {
|
||||
this.platformUtilsService.copyToClipboard(this.send.text.text);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("valueCopied", this.i18nService.t("sendTypeText")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("valueCopied", this.i18nService.t("sendTypeText")),
|
||||
});
|
||||
}
|
||||
|
||||
protected toggleText() {
|
||||
|
@ -12,7 +12,13 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService, NoItemsModule, SearchModule, TableDataSource } from "@bitwarden/components";
|
||||
import {
|
||||
DialogService,
|
||||
NoItemsModule,
|
||||
SearchModule,
|
||||
TableDataSource,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { HeaderModule } from "../../layouts/header/header.module";
|
||||
import { SharedModule } from "../../shared";
|
||||
@ -56,6 +62,7 @@ export class SendComponent extends BaseSendComponent {
|
||||
logService: LogService,
|
||||
sendApiService: SendApiService,
|
||||
dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
sendService,
|
||||
@ -68,6 +75,7 @@ export class SendComponent extends BaseSendComponent {
|
||||
logService,
|
||||
sendApiService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,39 +0,0 @@
|
||||
import { Component, OnDestroy, OnInit } from "@angular/core";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
|
||||
@Component({
|
||||
selector: "app-tools",
|
||||
templateUrl: "tools.component.html",
|
||||
})
|
||||
export class ToolsComponent implements OnInit, OnDestroy {
|
||||
private componentIsDestroyed$ = new Subject<boolean>();
|
||||
canAccessPremium = false;
|
||||
|
||||
constructor(
|
||||
private messagingService: MessagingService,
|
||||
private billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
this.billingAccountProfileStateService.hasPremiumFromAnySource$
|
||||
.pipe(takeUntil(this.componentIsDestroyed$))
|
||||
.subscribe((canAccessPremium: boolean) => {
|
||||
this.canAccessPremium = canAccessPremium;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.componentIsDestroyed$.next(true);
|
||||
this.componentIsDestroyed$.complete();
|
||||
}
|
||||
|
||||
premiumRequired() {
|
||||
if (!this.canAccessPremium) {
|
||||
this.messagingService.send("premiumRequired");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
@ -7,8 +7,7 @@ import { PolicyService } from "@bitwarden/common/admin-console/abstractions/poli
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
||||
import { ExportComponent as BaseExportComponent } from "@bitwarden/vault-export-ui";
|
||||
|
||||
@ -19,7 +18,7 @@ import { ExportComponent as BaseExportComponent } from "@bitwarden/vault-export-
|
||||
export class ExportComponent extends BaseExportComponent {
|
||||
constructor(
|
||||
i18nService: I18nService,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
toastService: ToastService,
|
||||
exportService: VaultExportServiceAbstraction,
|
||||
eventCollectionService: EventCollectionService,
|
||||
policyService: PolicyService,
|
||||
@ -31,7 +30,7 @@ export class ExportComponent extends BaseExportComponent {
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
platformUtilsService,
|
||||
toastService,
|
||||
exportService,
|
||||
eventCollectionService,
|
||||
policyService,
|
||||
@ -45,6 +44,10 @@ export class ExportComponent extends BaseExportComponent {
|
||||
|
||||
protected saved() {
|
||||
super.saved();
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("exportSuccess"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("exportSuccess"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -8405,5 +8405,29 @@
|
||||
},
|
||||
"memberAccessReportDesc": {
|
||||
"message": "Ensure members have access to the right credentials and their accounts are secure. Use this report to obtain a CSV of member access and account configurations."
|
||||
},
|
||||
"higherKDFIterations": {
|
||||
"message": "Higher KDF iterations can help protect your master password from being brute forced by an attacker."
|
||||
},
|
||||
"incrementsOf100,000": {
|
||||
"message": "increments of 100,000"
|
||||
},
|
||||
"smallIncrements": {
|
||||
"message": "small increments"
|
||||
},
|
||||
"kdfIterationRecommends": {
|
||||
"message": "We recommend 600,000 or more"
|
||||
},
|
||||
"kdfToHighWarningIncreaseInIncrements": {
|
||||
"message": "For older devices, setting your KDF too high may lead to performance issues. Increase the value in $VALUE$ and test your devices.",
|
||||
"placeholders": {
|
||||
"value": {
|
||||
"content": "$1",
|
||||
"example":"increments of 100,000"
|
||||
}
|
||||
}
|
||||
},
|
||||
"providerReinstate":{
|
||||
"message": " Contact Customer Support to reinstate your subscription."
|
||||
}
|
||||
}
|
||||
|
@ -1,28 +0,0 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { ProviderService } from "@bitwarden/common/admin-console/abstractions/provider.service";
|
||||
import { Provider } from "@bitwarden/common/admin-console/models/domain/provider";
|
||||
|
||||
@Component({
|
||||
selector: "provider-manage",
|
||||
templateUrl: "manage.component.html",
|
||||
})
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
|
||||
export class ManageComponent implements OnInit {
|
||||
provider: Provider;
|
||||
accessEvents = false;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private providerService: ProviderService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
// eslint-disable-next-line rxjs-angular/prefer-takeuntil, rxjs/no-async-subscribe
|
||||
this.route.parent.params.subscribe(async (params) => {
|
||||
this.provider = await this.providerService.get(params.providerId);
|
||||
this.accessEvents = this.provider.useEvents;
|
||||
});
|
||||
}
|
||||
}
|
@ -43,6 +43,10 @@ export class SubscriptionStatusComponent {
|
||||
}
|
||||
|
||||
get status(): string {
|
||||
if (this.subscription.cancelAt && this.subscription.status === "active") {
|
||||
this.subscription.status = "pending_cancellation";
|
||||
}
|
||||
|
||||
return this.subscription.status;
|
||||
}
|
||||
|
||||
@ -151,13 +155,15 @@ export class SubscriptionStatusComponent {
|
||||
},
|
||||
date: {
|
||||
label: cancellationDateLabel,
|
||||
value: this.subscription.currentPeriodEndDate.toDateString(),
|
||||
value: this.subscription.cancelAt,
|
||||
},
|
||||
callout: {
|
||||
severity: "warning",
|
||||
header: pendingCancellationText,
|
||||
body: this.i18nService.t("subscriptionPendingCanceled"),
|
||||
showReinstatementButton: true,
|
||||
body:
|
||||
this.i18nService.t("subscriptionPendingCanceled") +
|
||||
this.i18nService.t("providerReinstate"),
|
||||
showReinstatementButton: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
UsernameGeneratorOptions,
|
||||
} from "@bitwarden/common/tools/generator/username";
|
||||
import { EmailForwarderOptions } from "@bitwarden/common/tools/models/domain/email-forwarder-options";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Directive()
|
||||
export class GeneratorComponent implements OnInit, OnDestroy {
|
||||
@ -67,6 +68,7 @@ export class GeneratorComponent implements OnInit, OnDestroy {
|
||||
protected route: ActivatedRoute,
|
||||
protected ngZone: NgZone,
|
||||
private win: Window,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
this.typeOptions = [
|
||||
{ name: i18nService.t("password"), value: "password" },
|
||||
@ -317,11 +319,14 @@ export class GeneratorComponent implements OnInit, OnDestroy {
|
||||
password ? this.password : this.username,
|
||||
copyOptions,
|
||||
);
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
this.i18nService.t("valueCopied", this.i18nService.t(password ? "password" : "username")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "info",
|
||||
title: null,
|
||||
message: this.i18nService.t(
|
||||
"valueCopied",
|
||||
this.i18nService.t(password ? "password" : "username"),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
select() {
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
GeneratedPasswordHistory,
|
||||
PasswordGenerationServiceAbstraction,
|
||||
} from "@bitwarden/common/tools/generator/password";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Directive()
|
||||
export class PasswordGeneratorHistoryComponent implements OnInit {
|
||||
@ -16,6 +17,7 @@ export class PasswordGeneratorHistoryComponent implements OnInit {
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected i18nService: I18nService,
|
||||
private win: Window,
|
||||
protected toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -29,10 +31,10 @@ export class PasswordGeneratorHistoryComponent implements OnInit {
|
||||
copy(password: string) {
|
||||
const copyOptions = this.win != null ? { window: this.win } : null;
|
||||
this.platformUtilsService.copyToClipboard(password, copyOptions);
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
this.i18nService.t("valueCopied", this.i18nService.t("password")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "info",
|
||||
title: null,
|
||||
message: this.i18nService.t("valueCopied", this.i18nService.t("password")),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import { SendTextView } from "@bitwarden/common/tools/send/models/view/send-text
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
// Value = hours
|
||||
enum DatePreset {
|
||||
@ -120,6 +120,7 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
protected formBuilder: FormBuilder,
|
||||
protected billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected accountService: AccountService,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
this.typeOptions = [
|
||||
{ name: i18nService.t("sendTypeFile"), value: SendType.File, premium: true },
|
||||
@ -269,11 +270,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
this.formGroup.markAllAsTouched();
|
||||
|
||||
if (this.disableSend) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("sendDisabledWarning"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("sendDisabledWarning"),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -289,11 +290,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
this.send.type = this.type;
|
||||
|
||||
if (Utils.isNullOrWhitespace(this.send.name)) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("nameRequired"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("nameRequired"),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -302,22 +303,22 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
const fileEl = document.getElementById("file") as HTMLInputElement;
|
||||
const files = fileEl.files;
|
||||
if (files == null || files.length === 0) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("selectFile"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("selectFile"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
file = files[0];
|
||||
if (files[0].size > 524288000) {
|
||||
// 500 MB
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("maxFileSize"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("maxFileSize"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -340,11 +341,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
await this.handleCopyLinkToClipboard();
|
||||
return;
|
||||
}
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode ? "editedSend" : "createdSend"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t(this.editMode ? "editedSend" : "createdSend"),
|
||||
});
|
||||
});
|
||||
try {
|
||||
await this.formPromise;
|
||||
@ -377,7 +378,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
try {
|
||||
this.deletePromise = this.sendApiService.delete(this.send.id);
|
||||
await this.deletePromise;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedSend"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("deletedSend"),
|
||||
});
|
||||
await this.load();
|
||||
this.onDeletedSend.emit(this.send);
|
||||
return true;
|
||||
@ -470,11 +475,11 @@ export class AddEditComponent implements OnInit, OnDestroy {
|
||||
private async handleCopyLinkToClipboard() {
|
||||
const copySuccess = await this.copyLinkToClipboard(this.link);
|
||||
if (copySuccess ?? true) {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode ? "editedSend" : "createdSend"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t(this.editMode ? "editedSend" : "createdSend"),
|
||||
});
|
||||
} else {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
title: "",
|
||||
|
@ -20,7 +20,7 @@ import { SendType } from "@bitwarden/common/tools/send/enums/send-type";
|
||||
import { SendView } from "@bitwarden/common/tools/send/models/view/send.view";
|
||||
import { SendApiService } from "@bitwarden/common/tools/send/services/send-api.service.abstraction";
|
||||
import { SendService } from "@bitwarden/common/tools/send/services/send.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@Directive()
|
||||
export class SendComponent implements OnInit, OnDestroy {
|
||||
@ -76,6 +76,7 @@ export class SendComponent implements OnInit, OnDestroy {
|
||||
private logService: LogService,
|
||||
protected sendApiService: SendApiService,
|
||||
protected dialogService: DialogService,
|
||||
protected toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -186,7 +187,11 @@ export class SendComponent implements OnInit, OnDestroy {
|
||||
this.onSuccessfulRemovePassword();
|
||||
} else {
|
||||
// Default actions
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("removedPassword"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("removedPassword"),
|
||||
});
|
||||
await this.load();
|
||||
}
|
||||
} catch (e) {
|
||||
@ -220,7 +225,11 @@ export class SendComponent implements OnInit, OnDestroy {
|
||||
this.onSuccessfulDelete();
|
||||
} else {
|
||||
// Default actions
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("deletedSend"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("deletedSend"),
|
||||
});
|
||||
await this.refresh();
|
||||
}
|
||||
} catch (e) {
|
||||
@ -234,11 +243,11 @@ export class SendComponent implements OnInit, OnDestroy {
|
||||
const env = await firstValueFrom(this.environmentService.environment$);
|
||||
const link = env.getSendUrl() + s.accessId + "/" + s.urlB64Key;
|
||||
this.platformUtilsService.copyToClipboard(link);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("valueCopied", this.i18nService.t("sendLink")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("valueCopied", this.i18nService.t("sendLink")),
|
||||
});
|
||||
}
|
||||
|
||||
searchTextChanged() {
|
||||
|
@ -3,6 +3,7 @@ import { Observable } from "rxjs";
|
||||
import { VaultTimeoutAction } from "../../enums/vault-timeout-action.enum";
|
||||
import { UserId } from "../../types/guid";
|
||||
import { VaultTimeout } from "../../types/vault-timeout.type";
|
||||
import { SetTokensResult } from "../models/domain/set-tokens-result";
|
||||
import { DecodedAccessToken } from "../services/token.service";
|
||||
|
||||
export abstract class TokenService {
|
||||
@ -23,7 +24,7 @@ export abstract class TokenService {
|
||||
* @param refreshToken The optional refresh token to set. Note: this is undefined when using the CLI Login Via API Key flow
|
||||
* @param clientIdClientSecret The API Key Client ID and Client Secret to set.
|
||||
*
|
||||
* @returns A promise that resolves when the tokens have been set.
|
||||
* @returns A promise that resolves with the SetTokensResult containing the tokens that were set.
|
||||
*/
|
||||
setTokens: (
|
||||
accessToken: string,
|
||||
@ -31,7 +32,7 @@ export abstract class TokenService {
|
||||
vaultTimeout: VaultTimeout,
|
||||
refreshToken?: string,
|
||||
clientIdClientSecret?: [string, string],
|
||||
) => Promise<void>;
|
||||
) => Promise<SetTokensResult>;
|
||||
|
||||
/**
|
||||
* Clears the access token, refresh token, API Key Client ID, and API Key Client Secret out of memory, disk, and secure storage if supported.
|
||||
@ -47,13 +48,13 @@ export abstract class TokenService {
|
||||
* @param accessToken The access token to set.
|
||||
* @param vaultTimeoutAction The action to take when the vault times out.
|
||||
* @param vaultTimeout The timeout for the vault.
|
||||
* @returns A promise that resolves when the access token has been set.
|
||||
* @returns A promise that resolves with the access token that has been set.
|
||||
*/
|
||||
setAccessToken: (
|
||||
accessToken: string,
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
) => Promise<void>;
|
||||
) => Promise<string>;
|
||||
|
||||
// TODO: revisit having this public clear method approach once the state service is fully deprecated.
|
||||
/**
|
||||
@ -86,14 +87,14 @@ export abstract class TokenService {
|
||||
* @param clientId The API Key Client ID to set.
|
||||
* @param vaultTimeoutAction The action to take when the vault times out.
|
||||
* @param vaultTimeout The timeout for the vault.
|
||||
* @returns A promise that resolves when the API Key Client ID has been set.
|
||||
* @returns A promise that resolves with the API Key Client ID that has been set.
|
||||
*/
|
||||
setClientId: (
|
||||
clientId: string,
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId?: UserId,
|
||||
) => Promise<void>;
|
||||
) => Promise<string>;
|
||||
|
||||
/**
|
||||
* Gets the API Key Client ID for the active user.
|
||||
@ -106,14 +107,14 @@ export abstract class TokenService {
|
||||
* @param clientSecret The API Key Client Secret to set.
|
||||
* @param vaultTimeoutAction The action to take when the vault times out.
|
||||
* @param vaultTimeout The timeout for the vault.
|
||||
* @returns A promise that resolves when the API Key Client Secret has been set.
|
||||
* @returns A promise that resolves with the client secret that has been set.
|
||||
*/
|
||||
setClientSecret: (
|
||||
clientSecret: string,
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId?: UserId,
|
||||
) => Promise<void>;
|
||||
) => Promise<string>;
|
||||
|
||||
/**
|
||||
* Gets the API Key Client Secret for the active user.
|
||||
|
10
libs/common/src/auth/models/domain/set-tokens-result.ts
Normal file
10
libs/common/src/auth/models/domain/set-tokens-result.ts
Normal file
@ -0,0 +1,10 @@
|
||||
export class SetTokensResult {
|
||||
constructor(accessToken: string, refreshToken?: string, clientIdSecretPair?: [string, string]) {
|
||||
this.accessToken = accessToken;
|
||||
this.refreshToken = refreshToken;
|
||||
this.clientIdSecretPair = clientIdSecretPair;
|
||||
}
|
||||
accessToken: string;
|
||||
refreshToken?: string;
|
||||
clientIdSecretPair?: [string, string];
|
||||
}
|
@ -15,6 +15,7 @@ import { SymmetricCryptoKey } from "../../platform/models/domain/symmetric-crypt
|
||||
import { CsprngArray } from "../../types/csprng";
|
||||
import { UserId } from "../../types/guid";
|
||||
import { VaultTimeout, VaultTimeoutStringType } from "../../types/vault-timeout.type";
|
||||
import { SetTokensResult } from "../models/domain/set-tokens-result";
|
||||
|
||||
import { ACCOUNT_ACTIVE_ACCOUNT_ID } from "./account.service";
|
||||
import {
|
||||
@ -232,7 +233,7 @@ describe("TokenService", () => {
|
||||
describe("Memory storage tests", () => {
|
||||
it("set the access token in memory", async () => {
|
||||
// Act
|
||||
await tokenService.setAccessToken(
|
||||
const result = await tokenService.setAccessToken(
|
||||
accessTokenJwt,
|
||||
memoryVaultTimeoutAction,
|
||||
memoryVaultTimeout,
|
||||
@ -241,13 +242,14 @@ describe("TokenService", () => {
|
||||
expect(
|
||||
singleUserStateProvider.getFake(userIdFromAccessToken, ACCESS_TOKEN_MEMORY).nextMock,
|
||||
).toHaveBeenCalledWith(accessTokenJwt);
|
||||
expect(result).toEqual(accessTokenJwt);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Disk storage tests (secure storage not supported on platform)", () => {
|
||||
it("should set the access token in disk", async () => {
|
||||
// Act
|
||||
await tokenService.setAccessToken(
|
||||
const result = await tokenService.setAccessToken(
|
||||
accessTokenJwt,
|
||||
diskVaultTimeoutAction,
|
||||
diskVaultTimeout,
|
||||
@ -256,6 +258,7 @@ describe("TokenService", () => {
|
||||
expect(
|
||||
singleUserStateProvider.getFake(userIdFromAccessToken, ACCESS_TOKEN_DISK).nextMock,
|
||||
).toHaveBeenCalledWith(accessTokenJwt);
|
||||
expect(result).toEqual(accessTokenJwt);
|
||||
});
|
||||
});
|
||||
|
||||
@ -295,7 +298,7 @@ describe("TokenService", () => {
|
||||
secureStorageService.get.mockResolvedValueOnce(null).mockResolvedValue(accessTokenKeyB64);
|
||||
|
||||
// Act
|
||||
await tokenService.setAccessToken(
|
||||
const result = await tokenService.setAccessToken(
|
||||
accessTokenJwt,
|
||||
diskVaultTimeoutAction,
|
||||
diskVaultTimeout,
|
||||
@ -318,6 +321,9 @@ describe("TokenService", () => {
|
||||
expect(
|
||||
singleUserStateProvider.getFake(userIdFromAccessToken, ACCESS_TOKEN_MEMORY).nextMock,
|
||||
).toHaveBeenCalledWith(null);
|
||||
|
||||
// assert that the decrypted access token was returned
|
||||
expect(result).toEqual(accessTokenJwt);
|
||||
});
|
||||
|
||||
it("should fallback to disk storage for the access token if the access token cannot be set in secure storage", async () => {
|
||||
@ -331,7 +337,7 @@ describe("TokenService", () => {
|
||||
secureStorageService.get.mockResolvedValueOnce(null).mockResolvedValue(null);
|
||||
|
||||
// Act
|
||||
await tokenService.setAccessToken(
|
||||
const result = await tokenService.setAccessToken(
|
||||
accessTokenJwt,
|
||||
diskVaultTimeoutAction,
|
||||
diskVaultTimeout,
|
||||
@ -355,6 +361,9 @@ describe("TokenService", () => {
|
||||
expect(
|
||||
singleUserStateProvider.getFake(userIdFromAccessToken, ACCESS_TOKEN_DISK).nextMock,
|
||||
).toHaveBeenCalledWith(accessTokenJwt);
|
||||
|
||||
// assert that the decrypted access token was returned
|
||||
expect(result).toEqual(accessTokenJwt);
|
||||
});
|
||||
|
||||
it("should fallback to disk storage for the access token if secure storage errors on trying to get an existing access token key", async () => {
|
||||
@ -368,7 +377,7 @@ describe("TokenService", () => {
|
||||
secureStorageService.get.mockRejectedValue(new Error(secureStorageError));
|
||||
|
||||
// Act
|
||||
await tokenService.setAccessToken(
|
||||
const result = await tokenService.setAccessToken(
|
||||
accessTokenJwt,
|
||||
diskVaultTimeoutAction,
|
||||
diskVaultTimeout,
|
||||
@ -385,6 +394,9 @@ describe("TokenService", () => {
|
||||
expect(
|
||||
singleUserStateProvider.getFake(userIdFromAccessToken, ACCESS_TOKEN_DISK).nextMock,
|
||||
).toHaveBeenCalledWith(accessTokenJwt);
|
||||
|
||||
// assert that the decrypted access token was returned
|
||||
expect(result).toEqual(accessTokenJwt);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -2376,18 +2388,21 @@ describe("TokenService", () => {
|
||||
const clientId = "clientId";
|
||||
const clientSecret = "clientSecret";
|
||||
|
||||
(tokenService as any)._setAccessToken = jest.fn();
|
||||
// any hack allows for mocking private method.
|
||||
(tokenService as any).setRefreshToken = jest.fn();
|
||||
tokenService.setClientId = jest.fn();
|
||||
tokenService.setClientSecret = jest.fn();
|
||||
(tokenService as any)._setAccessToken = jest.fn().mockReturnValue(accessTokenJwt);
|
||||
(tokenService as any).setRefreshToken = jest.fn().mockReturnValue(refreshToken);
|
||||
tokenService.setClientId = jest.fn().mockReturnValue(clientId);
|
||||
tokenService.setClientSecret = jest.fn().mockReturnValue(clientSecret);
|
||||
|
||||
// Act
|
||||
// Note: passing a valid access token so that a valid user id can be determined from the access token
|
||||
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken, [
|
||||
clientId,
|
||||
clientSecret,
|
||||
]);
|
||||
const result = await tokenService.setTokens(
|
||||
accessTokenJwt,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
refreshToken,
|
||||
[clientId, clientSecret],
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect((tokenService as any)._setAccessToken).toHaveBeenCalledWith(
|
||||
@ -2417,6 +2432,44 @@ describe("TokenService", () => {
|
||||
vaultTimeout,
|
||||
userIdFromAccessToken,
|
||||
);
|
||||
|
||||
expect(result).toStrictEqual(
|
||||
new SetTokensResult(accessTokenJwt, refreshToken, [clientId, clientSecret]),
|
||||
);
|
||||
});
|
||||
|
||||
it("does not try to set the refresh token when it is not passed in", async () => {
|
||||
// Arrange
|
||||
const vaultTimeoutAction = VaultTimeoutAction.Lock;
|
||||
const vaultTimeout = 30;
|
||||
|
||||
(tokenService as any)._setAccessToken = jest.fn().mockReturnValue(accessTokenJwt);
|
||||
(tokenService as any).setRefreshToken = jest.fn();
|
||||
tokenService.setClientId = jest.fn();
|
||||
tokenService.setClientSecret = jest.fn();
|
||||
|
||||
// Act
|
||||
const result = await tokenService.setTokens(
|
||||
accessTokenJwt,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
null,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect((tokenService as any)._setAccessToken).toHaveBeenCalledWith(
|
||||
accessTokenJwt,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
userIdFromAccessToken,
|
||||
);
|
||||
|
||||
// any hack allows for testing private methods
|
||||
expect((tokenService as any).setRefreshToken).not.toHaveBeenCalled();
|
||||
expect(tokenService.setClientId).not.toHaveBeenCalled();
|
||||
expect(tokenService.setClientSecret).not.toHaveBeenCalled();
|
||||
|
||||
expect(result).toStrictEqual(new SetTokensResult(accessTokenJwt));
|
||||
});
|
||||
|
||||
it("does not try to set client id and client secret when they are not passed in", async () => {
|
||||
@ -2425,13 +2478,18 @@ describe("TokenService", () => {
|
||||
const vaultTimeoutAction = VaultTimeoutAction.Lock;
|
||||
const vaultTimeout = 30;
|
||||
|
||||
(tokenService as any)._setAccessToken = jest.fn();
|
||||
(tokenService as any).setRefreshToken = jest.fn();
|
||||
(tokenService as any)._setAccessToken = jest.fn().mockReturnValue(accessTokenJwt);
|
||||
(tokenService as any).setRefreshToken = jest.fn().mockReturnValue(refreshToken);
|
||||
tokenService.setClientId = jest.fn();
|
||||
tokenService.setClientSecret = jest.fn();
|
||||
|
||||
// Act
|
||||
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken);
|
||||
const result = await tokenService.setTokens(
|
||||
accessTokenJwt,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
refreshToken,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect((tokenService as any)._setAccessToken).toHaveBeenCalledWith(
|
||||
@ -2451,6 +2509,8 @@ describe("TokenService", () => {
|
||||
|
||||
expect(tokenService.setClientId).not.toHaveBeenCalled();
|
||||
expect(tokenService.setClientSecret).not.toHaveBeenCalled();
|
||||
|
||||
expect(result).toStrictEqual(new SetTokensResult(accessTokenJwt, refreshToken));
|
||||
});
|
||||
|
||||
it("throws an error when the access token is invalid", async () => {
|
||||
@ -2535,10 +2595,16 @@ describe("TokenService", () => {
|
||||
(tokenService as any).setRefreshToken = jest.fn();
|
||||
|
||||
// Act
|
||||
await tokenService.setTokens(accessTokenJwt, vaultTimeoutAction, vaultTimeout, refreshToken);
|
||||
const result = await tokenService.setTokens(
|
||||
accessTokenJwt,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
refreshToken,
|
||||
);
|
||||
|
||||
// Assert
|
||||
expect((tokenService as any).setRefreshToken).not.toHaveBeenCalled();
|
||||
expect(result).toStrictEqual(new SetTokensResult(accessTokenJwt));
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -21,6 +21,7 @@ import {
|
||||
import { UserId } from "../../types/guid";
|
||||
import { VaultTimeout, VaultTimeoutStringType } from "../../types/vault-timeout.type";
|
||||
import { TokenService as TokenServiceAbstraction } from "../abstractions/token.service";
|
||||
import { SetTokensResult } from "../models/domain/set-tokens-result";
|
||||
|
||||
import { ACCOUNT_ACTIVE_ACCOUNT_ID } from "./account.service";
|
||||
import {
|
||||
@ -160,7 +161,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
vaultTimeout: VaultTimeout,
|
||||
refreshToken?: string,
|
||||
clientIdClientSecret?: [string, string],
|
||||
): Promise<void> {
|
||||
): Promise<SetTokensResult> {
|
||||
if (!accessToken) {
|
||||
throw new Error("Access token is required.");
|
||||
}
|
||||
@ -181,16 +182,40 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
throw new Error("User id not found. Cannot set tokens.");
|
||||
}
|
||||
|
||||
await this._setAccessToken(accessToken, vaultTimeoutAction, vaultTimeout, userId);
|
||||
const newAccessToken = await this._setAccessToken(
|
||||
accessToken,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
userId,
|
||||
);
|
||||
|
||||
const newTokens = new SetTokensResult(newAccessToken);
|
||||
|
||||
if (refreshToken) {
|
||||
await this.setRefreshToken(refreshToken, vaultTimeoutAction, vaultTimeout, userId);
|
||||
newTokens.refreshToken = await this.setRefreshToken(
|
||||
refreshToken,
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
userId,
|
||||
);
|
||||
}
|
||||
|
||||
if (clientIdClientSecret != null) {
|
||||
await this.setClientId(clientIdClientSecret[0], vaultTimeoutAction, vaultTimeout, userId);
|
||||
await this.setClientSecret(clientIdClientSecret[1], vaultTimeoutAction, vaultTimeout, userId);
|
||||
const clientId = await this.setClientId(
|
||||
clientIdClientSecret[0],
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
userId,
|
||||
);
|
||||
const clientSecret = await this.setClientSecret(
|
||||
clientIdClientSecret[1],
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
userId,
|
||||
);
|
||||
newTokens.clientIdSecretPair = [clientId, clientSecret];
|
||||
}
|
||||
return newTokens;
|
||||
}
|
||||
|
||||
private async getAccessTokenKey(userId: UserId): Promise<AccessTokenKey | null> {
|
||||
@ -289,7 +314,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
): Promise<string> {
|
||||
const storageLocation = await this.determineStorageLocation(
|
||||
vaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
@ -302,6 +327,8 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
// store the access token directly. Instead, we encrypt with accessTokenKey and store that
|
||||
// in secure storage.
|
||||
|
||||
let decryptedAccessToken: string = null;
|
||||
|
||||
try {
|
||||
const encryptedAccessToken: EncString = await this.encryptAccessToken(
|
||||
accessToken,
|
||||
@ -313,6 +340,10 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
.get(userId, ACCESS_TOKEN_DISK)
|
||||
.update((_) => encryptedAccessToken.encryptedString);
|
||||
|
||||
// If we've successfully stored the encrypted access token to disk, we can return the decrypted access token
|
||||
// so that the caller can use it immediately.
|
||||
decryptedAccessToken = accessToken;
|
||||
|
||||
// TODO: PM-6408
|
||||
// 2024-02-20: Remove access token from memory so that we migrate to encrypt the access token over time.
|
||||
// Remove this call to remove the access token from memory after 3 months.
|
||||
@ -324,25 +355,23 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
);
|
||||
|
||||
// Fall back to disk storage for unecrypted access token
|
||||
await this.singleUserStateProvider
|
||||
decryptedAccessToken = await this.singleUserStateProvider
|
||||
.get(userId, ACCESS_TOKEN_DISK)
|
||||
.update((_) => accessToken);
|
||||
}
|
||||
|
||||
return;
|
||||
return decryptedAccessToken;
|
||||
}
|
||||
case TokenStorageLocation.Disk:
|
||||
// Access token stored on disk unencrypted as platform does not support secure storage
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, ACCESS_TOKEN_DISK)
|
||||
.update((_) => accessToken);
|
||||
return;
|
||||
case TokenStorageLocation.Memory:
|
||||
// Access token stored in memory due to vault timeout settings
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, ACCESS_TOKEN_MEMORY)
|
||||
.update((_) => accessToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -350,7 +379,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
accessToken: string,
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
): Promise<void> {
|
||||
): Promise<string> {
|
||||
if (!accessToken) {
|
||||
throw new Error("Access token is required.");
|
||||
}
|
||||
@ -370,7 +399,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
throw new Error("Vault Timeout Action is required.");
|
||||
}
|
||||
|
||||
await this._setAccessToken(accessToken, vaultTimeoutAction, vaultTimeout, userId);
|
||||
return await this._setAccessToken(accessToken, vaultTimeoutAction, vaultTimeout, userId);
|
||||
}
|
||||
|
||||
async clearAccessToken(userId?: UserId): Promise<void> {
|
||||
@ -486,7 +515,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId: UserId,
|
||||
): Promise<void> {
|
||||
): Promise<string> {
|
||||
// If we don't have a user id, we can't save the value
|
||||
if (!userId) {
|
||||
throw new Error("User id not found. Cannot save refresh token.");
|
||||
@ -509,6 +538,8 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
|
||||
switch (storageLocation) {
|
||||
case TokenStorageLocation.SecureStorage: {
|
||||
let decryptedRefreshToken: string = null;
|
||||
|
||||
try {
|
||||
await this.saveStringToSecureStorage(
|
||||
userId,
|
||||
@ -530,6 +561,10 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
throw new Error("Refresh token failed to save to secure storage.");
|
||||
}
|
||||
|
||||
// If we've successfully stored the encrypted refresh token, we can return the decrypted refresh token
|
||||
// so that the caller can use it immediately.
|
||||
decryptedRefreshToken = refreshToken;
|
||||
|
||||
// TODO: PM-6408
|
||||
// 2024-02-20: Remove refresh token from memory and disk so that we migrate to secure storage over time.
|
||||
// Remove these 2 calls to remove the refresh token from memory and disk after 3 months.
|
||||
@ -544,24 +579,22 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
);
|
||||
|
||||
// Fall back to disk storage for refresh token
|
||||
await this.singleUserStateProvider
|
||||
decryptedRefreshToken = await this.singleUserStateProvider
|
||||
.get(userId, REFRESH_TOKEN_DISK)
|
||||
.update((_) => refreshToken);
|
||||
}
|
||||
|
||||
return;
|
||||
return decryptedRefreshToken;
|
||||
}
|
||||
case TokenStorageLocation.Disk:
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, REFRESH_TOKEN_DISK)
|
||||
.update((_) => refreshToken);
|
||||
return;
|
||||
|
||||
case TokenStorageLocation.Memory:
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, REFRESH_TOKEN_MEMORY)
|
||||
.update((_) => refreshToken);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -644,7 +677,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId?: UserId,
|
||||
): Promise<void> {
|
||||
): Promise<string> {
|
||||
userId ??= await firstValueFrom(this.activeUserIdGlobalState.state$);
|
||||
|
||||
// If we don't have a user id, we can't save the value
|
||||
@ -668,11 +701,11 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
);
|
||||
|
||||
if (storageLocation === TokenStorageLocation.Disk) {
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, API_KEY_CLIENT_ID_DISK)
|
||||
.update((_) => clientId);
|
||||
} else if (storageLocation === TokenStorageLocation.Memory) {
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, API_KEY_CLIENT_ID_MEMORY)
|
||||
.update((_) => clientId);
|
||||
}
|
||||
@ -721,7 +754,7 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
vaultTimeoutAction: VaultTimeoutAction,
|
||||
vaultTimeout: VaultTimeout,
|
||||
userId?: UserId,
|
||||
): Promise<void> {
|
||||
): Promise<string> {
|
||||
userId ??= await firstValueFrom(this.activeUserIdGlobalState.state$);
|
||||
|
||||
if (!userId) {
|
||||
@ -744,11 +777,11 @@ export class TokenService implements TokenServiceAbstraction {
|
||||
);
|
||||
|
||||
if (storageLocation === TokenStorageLocation.Disk) {
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, API_KEY_CLIENT_SECRET_DISK)
|
||||
.update((_) => clientSecret);
|
||||
} else if (storageLocation === TokenStorageLocation.Memory) {
|
||||
await this.singleUserStateProvider
|
||||
return await this.singleUserStateProvider
|
||||
.get(userId, API_KEY_CLIENT_SECRET_MEMORY)
|
||||
.update((_) => clientSecret);
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ export class ProviderSubscriptionResponse extends BaseResponse {
|
||||
unpaidPeriodEndDate?: string;
|
||||
gracePeriod?: number | null;
|
||||
suspensionDate?: string;
|
||||
cancelAt?: string;
|
||||
|
||||
constructor(response: any) {
|
||||
super(response);
|
||||
@ -19,6 +20,7 @@ export class ProviderSubscriptionResponse extends BaseResponse {
|
||||
this.unpaidPeriodEndDate = this.getResponseProperty("unpaidPeriodEndDate");
|
||||
this.gracePeriod = this.getResponseProperty("gracePeriod");
|
||||
this.suspensionDate = this.getResponseProperty("suspensionDate");
|
||||
this.cancelAt = this.getResponseProperty("cancelAt");
|
||||
const plans = this.getResponseProperty("plans");
|
||||
if (plans != null) {
|
||||
this.plans = plans.map((i: any) => new ProviderPlanResponse(i));
|
||||
|
@ -249,7 +249,7 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
|
||||
async refreshIdentityToken(): Promise<any> {
|
||||
try {
|
||||
await this.doAuthRefresh();
|
||||
await this.refreshToken();
|
||||
} catch (e) {
|
||||
this.logService.error("Error refreshing access token: ", e);
|
||||
throw e;
|
||||
@ -1566,8 +1566,7 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
async getActiveBearerToken(): Promise<string> {
|
||||
let accessToken = await this.tokenService.getAccessToken();
|
||||
if (await this.tokenService.tokenNeedsRefresh()) {
|
||||
await this.doAuthRefresh();
|
||||
accessToken = await this.tokenService.getAccessToken();
|
||||
accessToken = await this.refreshToken();
|
||||
}
|
||||
return accessToken;
|
||||
}
|
||||
@ -1707,16 +1706,16 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
);
|
||||
}
|
||||
|
||||
protected async doAuthRefresh(): Promise<void> {
|
||||
protected async refreshToken(): Promise<string> {
|
||||
const refreshToken = await this.tokenService.getRefreshToken();
|
||||
if (refreshToken != null && refreshToken !== "") {
|
||||
return this.doRefreshToken();
|
||||
return this.refreshAccessToken();
|
||||
}
|
||||
|
||||
const clientId = await this.tokenService.getClientId();
|
||||
const clientSecret = await this.tokenService.getClientSecret();
|
||||
if (!Utils.isNullOrWhitespace(clientId) && !Utils.isNullOrWhitespace(clientSecret)) {
|
||||
return this.doApiTokenRefresh();
|
||||
return this.refreshApiToken();
|
||||
}
|
||||
|
||||
this.refreshAccessTokenErrorCallback();
|
||||
@ -1724,7 +1723,7 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
throw new Error("Cannot refresh access token, no refresh token or api keys are stored.");
|
||||
}
|
||||
|
||||
protected async doRefreshToken(): Promise<void> {
|
||||
protected async refreshAccessToken(): Promise<string> {
|
||||
const refreshToken = await this.tokenService.getRefreshToken();
|
||||
if (refreshToken == null || refreshToken === "") {
|
||||
throw new Error();
|
||||
@ -1770,19 +1769,20 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
this.vaultTimeoutSettingsService.getVaultTimeoutByUserId$(userId),
|
||||
);
|
||||
|
||||
await this.tokenService.setTokens(
|
||||
const refreshedTokens = await this.tokenService.setTokens(
|
||||
tokenResponse.accessToken,
|
||||
vaultTimeoutAction as VaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
tokenResponse.refreshToken,
|
||||
);
|
||||
return refreshedTokens.accessToken;
|
||||
} else {
|
||||
const error = await this.handleError(response, true, true);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
|
||||
protected async doApiTokenRefresh(): Promise<void> {
|
||||
protected async refreshApiToken(): Promise<string> {
|
||||
const clientId = await this.tokenService.getClientId();
|
||||
const clientSecret = await this.tokenService.getClientSecret();
|
||||
|
||||
@ -1810,11 +1810,12 @@ export class ApiService implements ApiServiceAbstraction {
|
||||
this.vaultTimeoutSettingsService.getVaultTimeoutByUserId$(userId),
|
||||
);
|
||||
|
||||
await this.tokenService.setAccessToken(
|
||||
const refreshedToken = await this.tokenService.setAccessToken(
|
||||
response.accessToken,
|
||||
vaultTimeoutAction as VaultTimeoutAction,
|
||||
vaultTimeout,
|
||||
);
|
||||
return refreshedToken;
|
||||
}
|
||||
|
||||
async send(
|
||||
|
@ -48,6 +48,7 @@ import {
|
||||
IconButtonModule,
|
||||
RadioButtonModule,
|
||||
SelectModule,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { ImportOption, ImportResult, ImportType } from "../models";
|
||||
@ -191,6 +192,7 @@ export class ImportComponent implements OnInit, OnDestroy {
|
||||
@Inject(ImportCollectionServiceAbstraction)
|
||||
@Optional()
|
||||
protected importCollectionService: ImportCollectionServiceAbstraction,
|
||||
protected toastService: ToastService,
|
||||
) {}
|
||||
|
||||
protected get importBlockedByPolicy(): boolean {
|
||||
@ -336,22 +338,22 @@ export class ImportComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
|
||||
if (importer === null) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("selectFormat"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("selectFormat"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const importContents = await this.setImportContents();
|
||||
|
||||
if (importContents == null || importContents === "") {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("selectFile"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("selectFile"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -502,11 +504,11 @@ export class ImportComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (this.importBlockedByPolicy && this.organizationId == null) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("personalOwnershipPolicyInEffectImports"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("personalOwnershipPolicyInEffectImports"),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -517,14 +519,6 @@ export class ImportComponent implements OnInit, OnDestroy {
|
||||
const fileEl = document.getElementById("import_input_file") as HTMLInputElement;
|
||||
const files = fileEl.files;
|
||||
let fileContents = this.formGroup.controls.fileContents.value;
|
||||
if ((files == null || files.length === 0) && (fileContents == null || fileContents === "")) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("selectFile"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (files != null && files.length > 0) {
|
||||
try {
|
||||
|
@ -15,7 +15,6 @@ import { EventType } from "@bitwarden/common/enums";
|
||||
import { FileDownloadService } from "@bitwarden/common/platform/abstractions/file-download/file-download.service";
|
||||
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 { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { EncryptedExportType } from "@bitwarden/common/tools/enums/encrypted-export-type.enum";
|
||||
import {
|
||||
@ -28,6 +27,7 @@ import {
|
||||
IconButtonModule,
|
||||
RadioButtonModule,
|
||||
SelectModule,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
import { VaultExportServiceAbstraction } from "@bitwarden/vault-export-core";
|
||||
|
||||
@ -123,7 +123,7 @@ export class ExportComponent implements OnInit, OnDestroy {
|
||||
|
||||
constructor(
|
||||
protected i18nService: I18nService,
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected toastService: ToastService,
|
||||
protected exportService: VaultExportServiceAbstraction,
|
||||
protected eventCollectionService: EventCollectionService,
|
||||
private policyService: PolicyService,
|
||||
@ -222,11 +222,11 @@ export class ExportComponent implements OnInit, OnDestroy {
|
||||
|
||||
submit = async () => {
|
||||
if (this.isFileEncryptedExport && this.filePassword != this.confirmFilePassword) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("filePasswordAndConfirmFilePasswordDoNotMatch"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@ -236,11 +236,11 @@ export class ExportComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
if (this.disabledByPolicy) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("personalVaultExportPolicyInEffect"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("personalVaultExportPolicyInEffect"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
575
package-lock.json
generated
575
package-lock.json
generated
@ -82,7 +82,7 @@
|
||||
"@angular/elements": "16.2.12",
|
||||
"@babel/core": "^7.24.6",
|
||||
"@babel/preset-env": "^7.24.6",
|
||||
"@compodoc/compodoc": "1.1.23",
|
||||
"@compodoc/compodoc": "1.1.25",
|
||||
"@electron/notarize": "2.3.0",
|
||||
"@electron/rebuild": "3.6.0",
|
||||
"@ngtools/webpack": "16.2.11",
|
||||
@ -2709,23 +2709,6 @@
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-proposal-private-methods": {
|
||||
"version": "7.18.6",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
|
||||
"integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
|
||||
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-create-class-features-plugin": "^7.18.6",
|
||||
"@babel/helper-plugin-utils": "^7.18.6"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/plugin-proposal-private-property-in-object": {
|
||||
"version": "7.21.0-placeholder-for-preset-env.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
|
||||
@ -4485,51 +4468,51 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc": {
|
||||
"version": "1.1.23",
|
||||
"resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.23.tgz",
|
||||
"integrity": "sha512-5Zfx+CHKTxLD+TxCGt1U8krnEBCWPVxCLt3jCJEN55AzhTluo8xlMenaXlJsuVqL4Lmo/OTTzEXrm9zoQKh/3w==",
|
||||
"version": "1.1.25",
|
||||
"resolved": "https://registry.npmjs.org/@compodoc/compodoc/-/compodoc-1.1.25.tgz",
|
||||
"integrity": "sha512-MsTEv6S0JGkdXc8pFp3yB/r8Lw49YenD0TCXyIVAmQhWNDtGWi4m2TGz02hdiKAlTJ1McQJFuyXWiItTQtje0A==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/schematics": "14.2.12",
|
||||
"@babel/core": "^7.23.3",
|
||||
"@babel/plugin-proposal-private-methods": "^7.18.6",
|
||||
"@babel/preset-env": "^7.23.3",
|
||||
"@angular-devkit/schematics": "18.0.1",
|
||||
"@babel/core": "^7.24.6",
|
||||
"@babel/plugin-transform-private-methods": "^7.24.6",
|
||||
"@babel/preset-env": "^7.24.6",
|
||||
"@compodoc/live-server": "^1.2.3",
|
||||
"@compodoc/ngd-transformer": "^2.1.3",
|
||||
"bootstrap.native": "^5.0.10",
|
||||
"bootstrap.native": "^5.0.12",
|
||||
"chalk": "4.1.2",
|
||||
"cheerio": "^1.0.0-rc.12",
|
||||
"chokidar": "^3.5.3",
|
||||
"chokidar": "^3.6.0",
|
||||
"colors": "1.4.0",
|
||||
"commander": "^11.1.0",
|
||||
"cosmiconfig": "^8.3.6",
|
||||
"commander": "^12.1.0",
|
||||
"cosmiconfig": "^9.0.0",
|
||||
"decache": "^4.6.2",
|
||||
"es6-shim": "^0.35.8",
|
||||
"fancy-log": "^2.0.0",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs-extra": "^11.1.1",
|
||||
"glob": "^10.3.10",
|
||||
"fs-extra": "^11.2.0",
|
||||
"glob": "^10.4.1",
|
||||
"handlebars": "^4.7.8",
|
||||
"html-entities": "^2.4.0",
|
||||
"i18next": "^23.7.6",
|
||||
"html-entities": "^2.5.2",
|
||||
"i18next": "^23.11.5",
|
||||
"json5": "^2.2.3",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.8.1",
|
||||
"loglevel": "^1.9.1",
|
||||
"loglevel-plugin-prefix": "^0.8.4",
|
||||
"lunr": "^2.3.9",
|
||||
"marked": "7.0.3",
|
||||
"minimist": "^1.2.8",
|
||||
"opencollective-postinstall": "^2.0.3",
|
||||
"os-name": "4.0.1",
|
||||
"pdfjs-dist": "2.12.313",
|
||||
"pdfmake": "^0.2.8",
|
||||
"pdfmake": "^0.2.10",
|
||||
"prismjs": "^1.29.0",
|
||||
"semver": "^7.5.4",
|
||||
"semver": "^7.6.2",
|
||||
"svg-pan-zoom": "^3.6.1",
|
||||
"tablesort": "^5.3.0",
|
||||
"traverse": "^0.6.7",
|
||||
"ts-morph": "^20.0.0",
|
||||
"traverse": "^0.6.9",
|
||||
"ts-morph": "^22.0.0",
|
||||
"uuid": "^9.0.1",
|
||||
"vis": "^4.21.0-EOL",
|
||||
"zepto": "^1.2.0"
|
||||
@ -4538,23 +4521,25 @@
|
||||
"compodoc": "bin/index-cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
"node": ">= 16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/@angular-devkit/core": {
|
||||
"version": "14.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-14.2.12.tgz",
|
||||
"integrity": "sha512-tg1+deEZdm3fgk2BQ6y7tujciL6qhtN5Ums266lX//kAZeZ4nNNXTBT+oY5xgfjvmLbW+xKg0XZrAS0oIRKY5g==",
|
||||
"version": "18.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-18.0.1.tgz",
|
||||
"integrity": "sha512-91eKZoObs+wRgwssw81Y/94Nvixj0WqJkNusBAg+gAfZTCEeJoGGZJkRK8wrONbM79C3Bx8lN/TfSIPRbjnfOQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "8.11.0",
|
||||
"ajv-formats": "2.1.1",
|
||||
"jsonc-parser": "3.1.0",
|
||||
"rxjs": "6.6.7",
|
||||
"ajv": "8.13.0",
|
||||
"ajv-formats": "3.0.1",
|
||||
"jsonc-parser": "3.2.1",
|
||||
"picomatch": "4.0.2",
|
||||
"rxjs": "7.8.1",
|
||||
"source-map": "0.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || >=16.10.0",
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
},
|
||||
@ -4568,182 +4553,126 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/@angular-devkit/schematics": {
|
||||
"version": "14.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-14.2.12.tgz",
|
||||
"integrity": "sha512-MN5yGR+SSSPPBBVMf4cifDJn9u0IYvxiHst+HWokH2AkBYy+vB1x8jYES2l1wkiISD7nvjTixfqX+Y95oMBoLg==",
|
||||
"version": "18.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-18.0.1.tgz",
|
||||
"integrity": "sha512-AKcEGa3fIgyXT6XTQZWEJZzgmcqlB89fcF7JFOuz4rgQfRmnE2xFw37lKE6ZclCOSiEoffAvgrL8acjdPI1ouw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@angular-devkit/core": "14.2.12",
|
||||
"jsonc-parser": "3.1.0",
|
||||
"magic-string": "0.26.2",
|
||||
"@angular-devkit/core": "18.0.1",
|
||||
"jsonc-parser": "3.2.1",
|
||||
"magic-string": "0.30.10",
|
||||
"ora": "5.4.1",
|
||||
"rxjs": "6.6.7"
|
||||
"rxjs": "7.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.15.0 || >=16.10.0",
|
||||
"node": "^18.19.1 || ^20.11.1 || >=22.0.0",
|
||||
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||
"yarn": ">= 1.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/@babel/plugin-transform-async-to-generator": {
|
||||
"version": "7.24.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz",
|
||||
"integrity": "sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-module-imports": "^7.24.1",
|
||||
"@babel/helper-plugin-utils": "^7.24.0",
|
||||
"@babel/helper-remap-async-to-generator": "^7.22.20"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/@babel/preset-env": {
|
||||
"version": "7.24.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.3.tgz",
|
||||
"integrity": "sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@babel/compat-data": "^7.24.1",
|
||||
"@babel/helper-compilation-targets": "^7.23.6",
|
||||
"@babel/helper-plugin-utils": "^7.24.0",
|
||||
"@babel/helper-validator-option": "^7.23.5",
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1",
|
||||
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1",
|
||||
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1",
|
||||
"@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
|
||||
"@babel/plugin-syntax-async-generators": "^7.8.4",
|
||||
"@babel/plugin-syntax-class-properties": "^7.12.13",
|
||||
"@babel/plugin-syntax-class-static-block": "^7.14.5",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||
"@babel/plugin-syntax-export-namespace-from": "^7.8.3",
|
||||
"@babel/plugin-syntax-import-assertions": "^7.24.1",
|
||||
"@babel/plugin-syntax-import-attributes": "^7.24.1",
|
||||
"@babel/plugin-syntax-import-meta": "^7.10.4",
|
||||
"@babel/plugin-syntax-json-strings": "^7.8.3",
|
||||
"@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
|
||||
"@babel/plugin-syntax-numeric-separator": "^7.10.4",
|
||||
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
|
||||
"@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
|
||||
"@babel/plugin-syntax-optional-chaining": "^7.8.3",
|
||||
"@babel/plugin-syntax-private-property-in-object": "^7.14.5",
|
||||
"@babel/plugin-syntax-top-level-await": "^7.14.5",
|
||||
"@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
|
||||
"@babel/plugin-transform-arrow-functions": "^7.24.1",
|
||||
"@babel/plugin-transform-async-generator-functions": "^7.24.3",
|
||||
"@babel/plugin-transform-async-to-generator": "^7.24.1",
|
||||
"@babel/plugin-transform-block-scoped-functions": "^7.24.1",
|
||||
"@babel/plugin-transform-block-scoping": "^7.24.1",
|
||||
"@babel/plugin-transform-class-properties": "^7.24.1",
|
||||
"@babel/plugin-transform-class-static-block": "^7.24.1",
|
||||
"@babel/plugin-transform-classes": "^7.24.1",
|
||||
"@babel/plugin-transform-computed-properties": "^7.24.1",
|
||||
"@babel/plugin-transform-destructuring": "^7.24.1",
|
||||
"@babel/plugin-transform-dotall-regex": "^7.24.1",
|
||||
"@babel/plugin-transform-duplicate-keys": "^7.24.1",
|
||||
"@babel/plugin-transform-dynamic-import": "^7.24.1",
|
||||
"@babel/plugin-transform-exponentiation-operator": "^7.24.1",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.24.1",
|
||||
"@babel/plugin-transform-for-of": "^7.24.1",
|
||||
"@babel/plugin-transform-function-name": "^7.24.1",
|
||||
"@babel/plugin-transform-json-strings": "^7.24.1",
|
||||
"@babel/plugin-transform-literals": "^7.24.1",
|
||||
"@babel/plugin-transform-logical-assignment-operators": "^7.24.1",
|
||||
"@babel/plugin-transform-member-expression-literals": "^7.24.1",
|
||||
"@babel/plugin-transform-modules-amd": "^7.24.1",
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.24.1",
|
||||
"@babel/plugin-transform-modules-systemjs": "^7.24.1",
|
||||
"@babel/plugin-transform-modules-umd": "^7.24.1",
|
||||
"@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
|
||||
"@babel/plugin-transform-new-target": "^7.24.1",
|
||||
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1",
|
||||
"@babel/plugin-transform-numeric-separator": "^7.24.1",
|
||||
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
|
||||
"@babel/plugin-transform-object-super": "^7.24.1",
|
||||
"@babel/plugin-transform-optional-catch-binding": "^7.24.1",
|
||||
"@babel/plugin-transform-optional-chaining": "^7.24.1",
|
||||
"@babel/plugin-transform-parameters": "^7.24.1",
|
||||
"@babel/plugin-transform-private-methods": "^7.24.1",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
|
||||
"@babel/plugin-transform-property-literals": "^7.24.1",
|
||||
"@babel/plugin-transform-regenerator": "^7.24.1",
|
||||
"@babel/plugin-transform-reserved-words": "^7.24.1",
|
||||
"@babel/plugin-transform-shorthand-properties": "^7.24.1",
|
||||
"@babel/plugin-transform-spread": "^7.24.1",
|
||||
"@babel/plugin-transform-sticky-regex": "^7.24.1",
|
||||
"@babel/plugin-transform-template-literals": "^7.24.1",
|
||||
"@babel/plugin-transform-typeof-symbol": "^7.24.1",
|
||||
"@babel/plugin-transform-unicode-escapes": "^7.24.1",
|
||||
"@babel/plugin-transform-unicode-property-regex": "^7.24.1",
|
||||
"@babel/plugin-transform-unicode-regex": "^7.24.1",
|
||||
"@babel/plugin-transform-unicode-sets-regex": "^7.24.1",
|
||||
"@babel/preset-modules": "0.1.6-no-external-plugins",
|
||||
"babel-plugin-polyfill-corejs2": "^0.4.10",
|
||||
"babel-plugin-polyfill-corejs3": "^0.10.4",
|
||||
"babel-plugin-polyfill-regenerator": "^0.6.1",
|
||||
"core-js-compat": "^3.31.0",
|
||||
"semver": "^6.3.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.0.0-0"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/@babel/preset-env/node_modules/semver": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
|
||||
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/ajv": {
|
||||
"version": "8.11.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
|
||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||
"version": "8.13.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.13.0.tgz",
|
||||
"integrity": "sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2",
|
||||
"uri-js": "^4.2.2"
|
||||
"uri-js": "^4.4.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-corejs3": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz",
|
||||
"integrity": "sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==",
|
||||
"node_modules/@compodoc/compodoc/node_modules/ajv-formats": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
|
||||
"integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.1",
|
||||
"core-js-compat": "^3.36.1"
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||
"ajv": "^8.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"ajv": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/babel-plugin-polyfill-regenerator": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz",
|
||||
"integrity": "sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g==",
|
||||
"node_modules/@compodoc/compodoc/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
|
||||
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
|
||||
"dev": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/chokidar": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
|
||||
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-define-polyfill-provider": "^0.6.1"
|
||||
"anymatch": "~3.1.2",
|
||||
"braces": "~3.0.2",
|
||||
"glob-parent": "~5.1.2",
|
||||
"is-binary-path": "~2.1.0",
|
||||
"is-glob": "~4.0.1",
|
||||
"normalize-path": "~3.0.0",
|
||||
"readdirp": "~3.6.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://paulmillr.com/funding/"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/commander": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/cosmiconfig": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
|
||||
"integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"env-paths": "^2.2.1",
|
||||
"import-fresh": "^3.3.0",
|
||||
"js-yaml": "^4.1.0",
|
||||
"parse-json": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/d-fischer"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
|
||||
"typescript": ">=4.9.5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/fast-glob": {
|
||||
@ -4751,6 +4680,7 @@
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
@ -4762,42 +4692,62 @@
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/js-yaml": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
|
||||
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.1"
|
||||
},
|
||||
"bin": {
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/jsonc-parser": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.1.0.tgz",
|
||||
"integrity": "sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg==",
|
||||
"dev": true
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz",
|
||||
"integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/magic-string": {
|
||||
"version": "0.26.2",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.2.tgz",
|
||||
"integrity": "sha512-NzzlXpclt5zAbmo6h6jNc8zl2gNRGHvmsZW4IvZhTC4W7k4OlLP+S5YLussa/r3ixNT66KOQfNORlXHSOy/X4A==",
|
||||
"version": "0.30.10",
|
||||
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
|
||||
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"sourcemap-codec": "^1.4.8"
|
||||
},
|
||||
"@jridgewell/sourcemap-codec": "^1.4.15"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/rxjs": {
|
||||
"version": "6.6.7",
|
||||
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
|
||||
"integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
|
||||
"node_modules/@compodoc/compodoc/node_modules/semver": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^1.9.0"
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"npm": ">=2.0.0"
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@compodoc/compodoc/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@compodoc/live-server": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@compodoc/live-server/-/live-server-1.2.3.tgz",
|
||||
@ -5958,6 +5908,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"string-width": "^5.1.2",
|
||||
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||
@ -5975,6 +5926,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
|
||||
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -5987,6 +5939,7 @@
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@ -5998,13 +5951,15 @@
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@isaacs/cliui/node_modules/string-width": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"eastasianwidth": "^0.2.0",
|
||||
"emoji-regex": "^9.2.2",
|
||||
@ -6022,6 +5977,7 @@
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
@ -6037,6 +5993,7 @@
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.1.0",
|
||||
"string-width": "^5.0.1",
|
||||
@ -7213,6 +7170,7 @@
|
||||
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
|
||||
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
@ -11255,37 +11213,41 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common": {
|
||||
"version": "0.21.0",
|
||||
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.21.0.tgz",
|
||||
"integrity": "sha512-ES110Mmne5Vi4ypUKrtVQfXFDtCsDXiUiGxF6ILVlE90dDD4fdpC1LSjydl/ml7xJWKSDZwUYD2zkOePMSrPBA==",
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.23.0.tgz",
|
||||
"integrity": "sha512-m7Lllj9n/S6sOkCkRftpM7L24uvmfXQFedlW/4hENcuJH1HHm9u5EgxZb9uVjQSCGrbBWBkOGgcTxNg36r6ywA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-glob": "^3.2.12",
|
||||
"minimatch": "^7.4.3",
|
||||
"mkdirp": "^2.1.6",
|
||||
"fast-glob": "^3.3.2",
|
||||
"minimatch": "^9.0.3",
|
||||
"mkdirp": "^3.0.1",
|
||||
"path-browserify": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common/node_modules/minimatch": {
|
||||
"version": "7.4.6",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-7.4.6.tgz",
|
||||
"integrity": "sha512-sBz8G/YjVniEz6lKPNpKxXwazJe4c19fEfV2GDMX6AjFz+MX9uDWIZW8XreVhkFW3fkIdTv/gxWr/Kks5FFAVw==",
|
||||
"node_modules/@ts-morph/common/node_modules/fast-glob": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
|
||||
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
"@nodelib/fs.stat": "^2.0.2",
|
||||
"@nodelib/fs.walk": "^1.2.3",
|
||||
"glob-parent": "^5.1.2",
|
||||
"merge2": "^1.3.0",
|
||||
"micromatch": "^4.0.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
"node": ">=8.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ts-morph/common/node_modules/mkdirp": {
|
||||
"version": "2.1.6",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz",
|
||||
"integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==",
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "dist/cjs/src/bin.js"
|
||||
},
|
||||
@ -15318,10 +15280,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/bootstrap.native": {
|
||||
"version": "5.0.11",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap.native/-/bootstrap.native-5.0.11.tgz",
|
||||
"integrity": "sha512-bk2i4sQcQk2KuCTs1yygTa+JGjZOpKzIZ/It6TZZOO/Q+PmVGuKuIbrznXF64BUFxXaPNy7gO9LnE7vjGdauSQ==",
|
||||
"version": "5.0.12",
|
||||
"resolved": "https://registry.npmjs.org/bootstrap.native/-/bootstrap.native-5.0.12.tgz",
|
||||
"integrity": "sha512-qTiFBK7//IgdF9u67w3W91U8C2Fc3TGQh61xa0pbtHmD1YRncncFNNs+6ewG2tW7fBGGMXg57gj5d9Qamr0S+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@thednp/event-listener": "^2.0.4",
|
||||
"@thednp/shorty": "^2.0.0"
|
||||
@ -16491,10 +16454,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/code-block-writer": {
|
||||
"version": "12.0.0",
|
||||
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-12.0.0.tgz",
|
||||
"integrity": "sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==",
|
||||
"dev": true
|
||||
"version": "13.0.1",
|
||||
"resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.1.tgz",
|
||||
"integrity": "sha512-c5or4P6erEA69TxaxTNcHUNcIn+oyxSRTOWV+pSYF+z4epXqNvwvJ70XPGjPNgue83oAFAPBRQYwpAJ/Hpe/Sg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/code-point-at": {
|
||||
"version": "1.1.0",
|
||||
@ -18477,7 +18441,8 @@
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/easy-stack": {
|
||||
"version": "1.0.1",
|
||||
@ -21731,22 +21696,23 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.3.10",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
|
||||
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
|
||||
"version": "10.4.1",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.1.tgz",
|
||||
"integrity": "sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.5",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
|
||||
"path-scurry": "^1.10.1"
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.4",
|
||||
"minipass": "^7.1.2",
|
||||
"path-scurry": "^1.11.1"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
@ -23697,9 +23663,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "23.10.1",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.10.1.tgz",
|
||||
"integrity": "sha512-NDiIzFbcs3O9PXpfhkjyf7WdqFn5Vq6mhzhtkXzj51aOcNuPNcTwuYNuXCpHsanZGHlHKL35G7huoFeVic1hng==",
|
||||
"version": "23.11.5",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.5.tgz",
|
||||
"integrity": "sha512-41pvpVbW9rhZPk5xjCX2TPJi2861LEig/YRhUkY+1FQ2IQPS0bKUDYnEqY8XPPbB48h1uIwLnP9iiEfuSl20CA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
@ -23715,6 +23681,7 @@
|
||||
"url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.23.2"
|
||||
}
|
||||
@ -25028,10 +24995,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
|
||||
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz",
|
||||
"integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
@ -29531,10 +29499,11 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minipass": {
|
||||
"version": "7.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
|
||||
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
|
||||
"version": "7.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
}
|
||||
@ -32112,26 +32081,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry": {
|
||||
"version": "1.10.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
|
||||
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
|
||||
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^9.1.1 || ^10.0.0",
|
||||
"lru-cache": "^10.2.0",
|
||||
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": ">=16 || 14 >=14.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/path-scurry/node_modules/lru-cache": {
|
||||
"version": "10.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
|
||||
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
|
||||
"version": "10.2.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.2.tgz",
|
||||
"integrity": "sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "14 || >=16.14"
|
||||
}
|
||||
@ -32165,20 +32136,6 @@
|
||||
"through": "~2.3"
|
||||
}
|
||||
},
|
||||
"node_modules/pdfjs-dist": {
|
||||
"version": "2.12.313",
|
||||
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-2.12.313.tgz",
|
||||
"integrity": "sha512-1x6iXO4Qnv6Eb+YFdN5JdUzt4pAkxSp3aLAYPX93eQCyg/m7QFzXVWJHJVtoW48CI8HCXju4dSkhQZwoheL5mA==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"worker-loader": "^3.0.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"worker-loader": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/pdfmake": {
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/pdfmake/-/pdfmake-0.2.10.tgz",
|
||||
@ -36027,13 +35984,6 @@
|
||||
"deprecated": "See https://github.com/lydell/source-map-url#deprecated",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/sourcemap-codec": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
|
||||
"integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
|
||||
"deprecated": "Please use @jridgewell/sourcemap-codec instead",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/space-separated-tokens": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz",
|
||||
@ -36515,6 +36465,7 @@
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
@ -36590,6 +36541,7 @@
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^5.0.1"
|
||||
},
|
||||
@ -37668,10 +37620,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/traverse": {
|
||||
"version": "0.6.8",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.8.tgz",
|
||||
"integrity": "sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==",
|
||||
"version": "0.6.9",
|
||||
"resolved": "https://registry.npmjs.org/traverse/-/traverse-0.6.9.tgz",
|
||||
"integrity": "sha512-7bBrcF+/LQzSgFmT0X5YclVqQxtv7TDJ1f8Wj7ibBu/U6BMLeOpUxuZjV7rMc44UtKxlnMFigdhFAIszSX1DMg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"gopd": "^1.0.1",
|
||||
"typedarray.prototype.slice": "^1.0.3",
|
||||
"which-typed-array": "^1.1.15"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
@ -37812,13 +37770,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ts-morph": {
|
||||
"version": "20.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-20.0.0.tgz",
|
||||
"integrity": "sha512-JVmEJy2Wow5n/84I3igthL9sudQ8qzjh/6i4tmYCm6IqYyKFlNbJZi7oBdjyqcWSWYRu3CtL0xbT6fS03ESZIg==",
|
||||
"version": "22.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-22.0.0.tgz",
|
||||
"integrity": "sha512-M9MqFGZREyeb5fTl6gNHKZLqBQA0TjA1lea+CR48R8EBTDuWrNqW6ccC5QvjNR4s6wDumD3LTCjOFSp9iwlzaw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ts-morph/common": "~0.21.0",
|
||||
"code-block-writer": "^12.0.0"
|
||||
"@ts-morph/common": "~0.23.0",
|
||||
"code-block-writer": "^13.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/tsconfig-paths": {
|
||||
@ -38261,6 +38220,27 @@
|
||||
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
|
||||
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
|
||||
},
|
||||
"node_modules/typedarray.prototype.slice": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typedarray.prototype.slice/-/typedarray.prototype.slice-1.0.3.tgz",
|
||||
"integrity": "sha512-8WbVAQAUlENo1q3c3zZYuy5k9VzBQvp8AX9WOtbvyWlLM1v5JaSRmjubLjzHF4JFtptjH/5c/i95yaElvcjC0A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-abstract": "^1.23.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"typed-array-buffer": "^1.0.2",
|
||||
"typed-array-byte-offset": "^1.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.1.6",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
|
||||
@ -40142,6 +40122,7 @@
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
|
@ -22,7 +22,7 @@
|
||||
"test:watch": "jest --clearCache && jest --watch",
|
||||
"test:watch:all": "jest --watchAll",
|
||||
"test:types": "node ./scripts/test-types.js",
|
||||
"docs:json": "compodoc -p ./tsconfig.json -e json -d .",
|
||||
"docs:json": "compodoc -p ./tsconfig.json -e json -d . --disableRoutesGraph",
|
||||
"storybook": "ng run components:storybook",
|
||||
"build-storybook": "ng run components:build-storybook",
|
||||
"build-storybook:ci": "ng run components:build-storybook --webpack-stats-json",
|
||||
@ -43,7 +43,7 @@
|
||||
"@angular/elements": "16.2.12",
|
||||
"@babel/core": "^7.24.6",
|
||||
"@babel/preset-env": "^7.24.6",
|
||||
"@compodoc/compodoc": "1.1.23",
|
||||
"@compodoc/compodoc": "1.1.25",
|
||||
"@electron/notarize": "2.3.0",
|
||||
"@electron/rebuild": "3.6.0",
|
||||
"@ngtools/webpack": "16.2.11",
|
||||
|
Loading…
Reference in New Issue
Block a user