mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 16:53:34 +00:00
merge main
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@bitwarden/web-vault",
|
||||
"version": "2024.8.0",
|
||||
"version": "2024.8.1",
|
||||
"scripts": {
|
||||
"build:oss": "webpack",
|
||||
"build:bit": "webpack -c ../../bitwarden_license/bit-web/webpack.config.js",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="en" class="tw-h-full">
|
||||
<html lang="en" class="tw-h-full theme_light">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
@@ -16,9 +16,9 @@
|
||||
</head>
|
||||
|
||||
<body class="tw-min-h-screen !tw-min-w-0 tw-text-center tw-bg-background-alt tw-flex tw-flex-col">
|
||||
<main class="tw-max-w-3xl tw-mx-auto tw-mb-8 tw-px-2">
|
||||
<img src="images/logo.svg" width="200px" class="tw-py-16" alt="Bitwarden" />
|
||||
<img class="new-logo-themed tw-m-8" alt="Bitwarden" />
|
||||
|
||||
<main class="tw-max-w-3xl tw-mx-auto tw-px-2 tw-my-4">
|
||||
<h1 class="tw-mb-0 tw-h1">Sorry, this page isn't available.</h1>
|
||||
|
||||
<p class="tw-py-9 tw-mb-0">
|
||||
|
||||
@@ -96,7 +96,7 @@ export abstract class BaseMembersComponent<UserView extends UserViewTypes> {
|
||||
|
||||
abstract edit(user: UserView): void;
|
||||
abstract getUsers(): Promise<ListResponse<UserView> | UserView[]>;
|
||||
abstract deleteUser(id: string): Promise<void>;
|
||||
abstract removeUser(id: string): Promise<void>;
|
||||
abstract reinviteUser(id: string): Promise<void>;
|
||||
abstract confirmUser(user: UserView, publicKey: Uint8Array): Promise<void>;
|
||||
|
||||
@@ -132,7 +132,7 @@ export abstract class BaseMembersComponent<UserView extends UserViewTypes> {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.actionPromise = this.deleteUser(user.id);
|
||||
this.actionPromise = this.removeUser(user.id);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.toastService.showToast({
|
||||
|
||||
@@ -8,6 +8,7 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
||||
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 { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../core";
|
||||
import { EventExportService } from "../../tools/event-export";
|
||||
@@ -34,6 +35,7 @@ export abstract class BaseEventsComponent {
|
||||
protected platformUtilsService: PlatformUtilsService,
|
||||
protected logService: LogService,
|
||||
protected fileDownloadService: FileDownloadService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
const defaultDates = this.eventService.getDefaultDateFilters();
|
||||
this.start = defaultDates[0];
|
||||
@@ -164,11 +166,11 @@ export abstract class BaseEventsComponent {
|
||||
try {
|
||||
dates = this.eventService.formatDateFilters(this.start, this.end);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("invalidDateRange"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("invalidDateRange"),
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return dates;
|
||||
|
||||
@@ -22,7 +22,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserView } from "../organizations/core/views/organization-user.view";
|
||||
import { UserConfirmComponent } from "../organizations/manage/user-confirm.component";
|
||||
@@ -127,6 +127,7 @@ export abstract class BasePeopleComponent<
|
||||
protected userNamePipe: UserNamePipe,
|
||||
protected dialogService: DialogService,
|
||||
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
|
||||
protected toastService: ToastService,
|
||||
) {}
|
||||
|
||||
abstract edit(user: UserType): void;
|
||||
@@ -251,11 +252,11 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = this.deleteUser(user.id);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("removedUserId", this.userNamePipe.transform(user)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("removedUserId", this.userNamePipe.transform(user)),
|
||||
});
|
||||
this.removeUser(user);
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
@@ -282,11 +283,11 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = this.revokeUser(user.id);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("revokedUserId", this.userNamePipe.transform(user)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("revokedUserId", this.userNamePipe.transform(user)),
|
||||
});
|
||||
await this.load();
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
@@ -298,11 +299,11 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = this.restoreUser(user.id);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("restoredUserId", this.userNamePipe.transform(user)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("restoredUserId", this.userNamePipe.transform(user)),
|
||||
});
|
||||
await this.load();
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
@@ -318,11 +319,11 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = this.reinviteUser(user.id);
|
||||
try {
|
||||
await this.actionPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("hasBeenReinvited", this.userNamePipe.transform(user)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("hasBeenReinvited", this.userNamePipe.transform(user)),
|
||||
});
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
}
|
||||
@@ -344,11 +345,11 @@ export abstract class BasePeopleComponent<
|
||||
this.actionPromise = this.confirmUser(user, publicKey);
|
||||
await this.actionPromise;
|
||||
updateUser(this);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(user)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(user)),
|
||||
});
|
||||
} catch (e) {
|
||||
this.validationService.showError(e);
|
||||
throw e;
|
||||
|
||||
@@ -12,7 +12,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { DialogService, TableDataSource } from "@bitwarden/components";
|
||||
import { DialogService, TableDataSource, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../../core";
|
||||
import { SharedModule } from "../../../shared";
|
||||
@@ -63,6 +63,7 @@ export class EntityEventsComponent implements OnInit {
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private formBuilder: FormBuilder,
|
||||
private validationService: ValidationService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -109,11 +110,11 @@ export class EntityEventsComponent implements OnInit {
|
||||
this.filterFormGroup.value.end,
|
||||
);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("invalidDateRange"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("invalidDateRange"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import { FileDownloadService } from "@bitwarden/common/platform/abstractions/fil
|
||||
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 { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EventService } from "../../../core";
|
||||
import { EventExportService } from "../../../tools/event-export";
|
||||
@@ -22,6 +23,7 @@ import { BaseEventsComponent } from "../../common/base.events.component";
|
||||
const EVENT_SYSTEM_USER_TO_TRANSLATION: Record<EventSystemUser, string> = {
|
||||
[EventSystemUser.SCIM]: null, // SCIM acronym not able to be translated so just display SCIM
|
||||
[EventSystemUser.DomainVerification]: "domainVerification",
|
||||
[EventSystemUser.PublicApi]: "publicApi",
|
||||
};
|
||||
|
||||
@Component({
|
||||
@@ -50,6 +52,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private providerService: ProviderService,
|
||||
fileDownloadService: FileDownloadService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
eventService,
|
||||
@@ -58,6 +61,7 @@ export class EventsComponent extends BaseEventsComponent implements OnInit, OnDe
|
||||
platformUtilsService,
|
||||
logService,
|
||||
fileDownloadService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAdminService } from "../../../vault/core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../../vault/core/views/collection-admin.view";
|
||||
@@ -213,6 +213,7 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
private organizationService: OrganizationService,
|
||||
private accountService: AccountService,
|
||||
private collectionAdminService: CollectionAdminService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.tabIndex = params.initialTab ?? GroupAddEditTabType.Info;
|
||||
}
|
||||
@@ -280,11 +281,14 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (this.groupForm.invalid) {
|
||||
if (this.tabIndex !== GroupAddEditTabType.Info) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("groupInfo")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t(
|
||||
"fieldOnTabRequiresAttention",
|
||||
this.i18nService.t("groupInfo"),
|
||||
),
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -300,11 +304,14 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
|
||||
await this.groupService.save(groupView);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode ? "editedGroupId" : "createdGroupId", formValue.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t(
|
||||
this.editMode ? "editedGroupId" : "createdGroupId",
|
||||
formValue.name,
|
||||
),
|
||||
});
|
||||
|
||||
this.dialogRef.close(GroupAddEditDialogResultType.Saved);
|
||||
};
|
||||
@@ -325,11 +332,11 @@ export class GroupAddEditComponent implements OnInit, OnDestroy {
|
||||
|
||||
await this.groupService.delete(this.organizationId, this.groupId);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("deletedGroupId", this.group.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("deletedGroupId", this.group.name),
|
||||
});
|
||||
this.dialogRef.close(GroupAddEditDialogResultType.Deleted);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-conso
|
||||
import { OrganizationVerifyDeleteRecoverRequest } from "@bitwarden/common/admin-console/models/request/organization-verify-delete-recover.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../../shared/shared.module";
|
||||
|
||||
@@ -27,6 +28,7 @@ export class VerifyRecoverDeleteOrgComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private route: ActivatedRoute,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -44,11 +46,11 @@ export class VerifyRecoverDeleteOrgComponent implements OnInit {
|
||||
submit = async () => {
|
||||
const request = new OrganizationVerifyDeleteRecoverRequest(this.token);
|
||||
await this.apiService.deleteUsingToken(this.orgId, request);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("organizationDeleted"),
|
||||
this.i18nService.t("organizationDeletedDesc"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("organizationDeleted"),
|
||||
message: this.i18nService.t("organizationDeletedDesc"),
|
||||
});
|
||||
await this.router.navigate(["/"]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Component, Inject, OnInit } from "@angular/core";
|
||||
import { OrganizationUserService } from "@bitwarden/common/admin-console/abstractions/organization-user/organization-user.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService, TableDataSource } from "@bitwarden/components";
|
||||
import { DialogService, TableDataSource, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserView } from "../../../core";
|
||||
|
||||
@@ -24,6 +24,7 @@ export class BulkEnableSecretsManagerDialogComponent implements OnInit {
|
||||
private organizationUserService: OrganizationUserService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -35,11 +36,11 @@ export class BulkEnableSecretsManagerDialogComponent implements OnInit {
|
||||
this.data.orgId,
|
||||
this.dataSource.data.map((u) => u.id),
|
||||
);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("activatedAccessToSecretsManager"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("activatedAccessToSecretsManager"),
|
||||
});
|
||||
this.dialogRef.close();
|
||||
};
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ export class BulkRemoveComponent {
|
||||
submit = async () => {
|
||||
this.loading = true;
|
||||
try {
|
||||
const response = await this.deleteUsers();
|
||||
const response = await this.removeUsers();
|
||||
|
||||
response.data.forEach((entry) => {
|
||||
const error = entry.error !== "" ? entry.error : this.i18nService.t("bulkRemovedMessage");
|
||||
@@ -59,8 +59,8 @@ export class BulkRemoveComponent {
|
||||
this.loading = false;
|
||||
};
|
||||
|
||||
protected async deleteUsers() {
|
||||
return await this.organizationUserService.deleteManyOrganizationUsers(
|
||||
protected async removeUsers() {
|
||||
return await this.organizationUserService.removeManyOrganizationUsers(
|
||||
this.organizationId,
|
||||
this.users.map((user) => user.id),
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@ import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { CollectionAdminService } from "../../../../../vault/core/collection-admin.service";
|
||||
import { CollectionAdminView } from "../../../../../vault/core/views/collection-admin.view";
|
||||
@@ -143,6 +143,7 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
private dialogService: DialogService,
|
||||
private accountService: AccountService,
|
||||
organizationService: OrganizationService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.organization$ = organizationService
|
||||
.get$(this.params.organizationId)
|
||||
@@ -376,11 +377,11 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
) {
|
||||
this.permissionsGroup.value.manageUsers = true;
|
||||
(document.getElementById("manageUsers") as HTMLInputElement).checked = true;
|
||||
this.platformUtilsService.showToast(
|
||||
"info",
|
||||
null,
|
||||
this.i18nService.t("accountRecoveryManageUsers"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "info",
|
||||
title: null,
|
||||
message: this.i18nService.t("accountRecoveryManageUsers"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,11 +390,11 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
|
||||
if (this.formGroup.invalid) {
|
||||
if (this.tabIndex !== MemberDialogTab.Role) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("role")),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("fieldOnTabRequiresAttention", this.i18nService.t("role")),
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -401,11 +402,11 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
const organization = await firstValueFrom(this.organization$);
|
||||
|
||||
if (!organization.useCustomPermissions && this.customUserTypeSelected) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("customNonEnterpriseError"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("customNonEnterpriseError"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -452,11 +453,14 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
await this.userService.invite(emails, userView);
|
||||
}
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode ? "editedUserId" : "invitedUsers", this.params.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t(
|
||||
this.editMode ? "editedUserId" : "invitedUsers",
|
||||
this.params.name,
|
||||
),
|
||||
});
|
||||
this.close(MemberDialogResult.Saved);
|
||||
};
|
||||
|
||||
@@ -487,16 +491,16 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
await this.organizationUserService.deleteOrganizationUser(
|
||||
await this.organizationUserService.removeOrganizationUser(
|
||||
this.params.organizationId,
|
||||
this.params.organizationUserId,
|
||||
);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("removedUserId", this.params.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("removedUserId", this.params.name),
|
||||
});
|
||||
this.close(MemberDialogResult.Deleted);
|
||||
};
|
||||
|
||||
@@ -529,11 +533,11 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
this.params.organizationUserId,
|
||||
);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("revokedUserId", this.params.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("revokedUserId", this.params.name),
|
||||
});
|
||||
this.isRevoked = true;
|
||||
this.close(MemberDialogResult.Revoked);
|
||||
};
|
||||
@@ -548,11 +552,11 @@ export class MemberDialogComponent implements OnDestroy {
|
||||
this.params.organizationUserId,
|
||||
);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("restoredUserId", this.params.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("restoredUserId", this.params.name),
|
||||
});
|
||||
this.isRevoked = false;
|
||||
this.close(MemberDialogResult.Restored);
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
import { OrganizationUserResetPasswordService } from "../services/organization-user-reset-password/organization-user-reset-password.service";
|
||||
@@ -50,6 +50,7 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
private policyService: PolicyService,
|
||||
private logService: LogService,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -88,30 +89,30 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
this.platformUtilsService.copyToClipboard(value, { window: window });
|
||||
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")),
|
||||
});
|
||||
}
|
||||
|
||||
async submit() {
|
||||
// Validation
|
||||
if (this.newPassword == null || this.newPassword === "") {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("masterPasswordRequired"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("masterPasswordRequired"),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.newPassword.length < Utils.minimumPasswordLength) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("masterPasswordMinlength", Utils.minimumPasswordLength),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("masterPasswordMinlength", Utils.minimumPasswordLength),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -123,11 +124,11 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
this.enforcedPolicyOptions,
|
||||
)
|
||||
) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("masterPasswordPolicyRequirementsNotMet"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("masterPasswordPolicyRequirementsNotMet"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -151,11 +152,11 @@ export class ResetPasswordComponent implements OnInit, OnDestroy {
|
||||
this.organizationId,
|
||||
);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("resetPasswordSuccess"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("resetPasswordSuccess"),
|
||||
});
|
||||
this.passwordReset.emit();
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
|
||||
import { Policy } from "@bitwarden/common/admin-console/models/domain/policy";
|
||||
import { OrganizationKeysRequest } from "@bitwarden/common/admin-console/models/request/organization-keys.request";
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billilng-api.service.abstraction";
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||
import { isNotSelfUpgradable, ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -269,8 +269,8 @@ export class MembersComponent extends BaseMembersComponent<OrganizationUserView>
|
||||
return collectionMap;
|
||||
}
|
||||
|
||||
deleteUser(id: string): Promise<void> {
|
||||
return this.organizationUserService.deleteOrganizationUser(this.organization.id, id);
|
||||
removeUser(id: string): Promise<void> {
|
||||
return this.organizationUserService.removeOrganizationUser(this.organization.id, id);
|
||||
}
|
||||
|
||||
revokeUser(id: string): Promise<void> {
|
||||
|
||||
@@ -15,7 +15,7 @@ import { PolicyRequest } from "@bitwarden/common/admin-console/models/request/po
|
||||
import { PolicyResponse } from "@bitwarden/common/admin-console/models/response/policy.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { BasePolicy, BasePolicyComponent } from "../policies";
|
||||
|
||||
@@ -58,6 +58,7 @@ export class PolicyEditComponent implements AfterViewInit {
|
||||
private cdr: ChangeDetectorRef,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef<PolicyEditDialogResult>,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
get policy(): BasePolicy {
|
||||
return this.data.policy;
|
||||
@@ -95,7 +96,7 @@ export class PolicyEditComponent implements AfterViewInit {
|
||||
try {
|
||||
request = await this.policyComponent.buildRequest(this.data.policiesEnabledMap);
|
||||
} catch (e) {
|
||||
this.platformUtilsService.showToast("error", null, e.message);
|
||||
this.toastService.showToast({ variant: "error", title: null, message: e.message });
|
||||
return;
|
||||
}
|
||||
this.formPromise = this.policyApiService.putPolicy(
|
||||
@@ -104,11 +105,11 @@ export class PolicyEditComponent implements AfterViewInit {
|
||||
request,
|
||||
);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("editedPolicyId", this.i18nService.t(this.data.policy.name)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("editedPolicyId", this.i18nService.t(this.data.policy.name)),
|
||||
});
|
||||
this.dialogRef.close(PolicyEditDialogResult.Saved);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.se
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { ApiKeyComponent } from "../../../auth/settings/security/api-key.component";
|
||||
import { PurgeVaultComponent } from "../../../vault/settings/purge-vault.component";
|
||||
@@ -77,6 +77,7 @@ export class AccountComponent implements OnInit, OnDestroy {
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -167,7 +168,11 @@ export class AccountComponent implements OnInit, OnDestroy {
|
||||
|
||||
await this.organizationApiService.save(this.organizationId, request);
|
||||
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("organizationUpdated"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("organizationUpdated"),
|
||||
});
|
||||
};
|
||||
|
||||
submitCollectionManagement = async () => {
|
||||
@@ -184,11 +189,11 @@ export class AccountComponent implements OnInit, OnDestroy {
|
||||
|
||||
await this.organizationApiService.updateCollectionManagement(this.organizationId, request);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("updatedCollectionManagement"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("updatedCollectionManagement"),
|
||||
});
|
||||
};
|
||||
|
||||
async deleteOrganization() {
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { UserVerificationModule } from "../../../../auth/shared/components/user-verification";
|
||||
import { SharedModule } from "../../../../shared/shared.module";
|
||||
@@ -94,6 +94,7 @@ export class DeleteOrganizationDialogComponent implements OnInit, OnDestroy {
|
||||
private organizationService: OrganizationService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
@@ -121,11 +122,11 @@ export class DeleteOrganizationDialogComponent implements OnInit, OnDestroy {
|
||||
.buildRequest(this.formGroup.value.secret)
|
||||
.then((request) => this.organizationApiService.delete(this.organization.id, request));
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("organizationDeleted"),
|
||||
this.i18nService.t("organizationDeletedDesc"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("organizationDeleted"),
|
||||
message: this.i18nService.t("organizationDeletedDesc"),
|
||||
});
|
||||
this.dialogRef.close(DeleteOrganizationDialogResult.Deleted);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationPlansComponent } from "../../../billing";
|
||||
import { SharedModule } from "../../../shared";
|
||||
@@ -68,6 +68,7 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
||||
private organizationService: OrganizationService,
|
||||
private dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -76,12 +77,12 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
||||
this.route.queryParams.pipe(first()).subscribe(async (qParams) => {
|
||||
const error = qParams.token == null;
|
||||
if (error) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("sponsoredFamiliesAcceptFailed"),
|
||||
{ timeout: 10000 },
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("sponsoredFamiliesAcceptFailed"),
|
||||
timeout: 10000,
|
||||
});
|
||||
// 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(["/"]);
|
||||
@@ -139,11 +140,11 @@ export class FamiliesForEnterpriseSetupComponent implements OnInit, OnDestroy {
|
||||
request.sponsoredOrganizationId = organizationId;
|
||||
|
||||
await this.apiService.postRedeemSponsorship(this.token, request);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("sponsoredFamiliesOfferRedeemed"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("sponsoredFamiliesOfferRedeemed"),
|
||||
});
|
||||
await this.syncService.fullSync(true);
|
||||
|
||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||
|
||||
@@ -8,7 +8,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserResetPasswordService } from "../members/services/organization-user-reset-password/organization-user-reset-password.service";
|
||||
|
||||
@@ -29,6 +29,7 @@ export class EnrollMasterPasswordReset {
|
||||
syncService: SyncService,
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
const result = await UserVerificationDialogComponent.open(dialogService, {
|
||||
title: "enrollAccountRecovery",
|
||||
@@ -71,7 +72,11 @@ export class EnrollMasterPasswordReset {
|
||||
|
||||
// Enrollment succeeded
|
||||
try {
|
||||
platformUtilsService.showToast("success", null, i18nService.t("enrollPasswordResetSuccess"));
|
||||
toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: i18nService.t("enrollPasswordResetSuccess"),
|
||||
});
|
||||
await syncService.fullSync(true);
|
||||
} catch (e) {
|
||||
logService.error(e);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { ProviderVerifyRecoverDeleteRequest } from "@bitwarden/common/admin-cons
|
||||
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 { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-verify-recover-delete-provider",
|
||||
@@ -27,6 +28,7 @@ export class VerifyRecoverDeleteProviderComponent implements OnInit {
|
||||
private i18nService: I18nService,
|
||||
private route: ActivatedRoute,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -48,11 +50,11 @@ export class VerifyRecoverDeleteProviderComponent implements OnInit {
|
||||
request,
|
||||
);
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("providerDeleted"),
|
||||
this.i18nService.t("providerDeletedDesc"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("providerDeleted"),
|
||||
message: this.i18nService.t("providerDeletedDesc"),
|
||||
});
|
||||
await this.router.navigate(["/"]);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -8,6 +8,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.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 { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-hint",
|
||||
@@ -30,8 +31,17 @@ export class HintComponent extends BaseHintComponent implements OnInit {
|
||||
logService: LogService,
|
||||
loginEmailService: LoginEmailServiceAbstraction,
|
||||
private formBuilder: FormBuilder,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(router, i18nService, apiService, platformUtilsService, logService, loginEmailService);
|
||||
super(
|
||||
router,
|
||||
i18nService,
|
||||
apiService,
|
||||
platformUtilsService,
|
||||
logService,
|
||||
loginEmailService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
@@ -28,6 +28,8 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { PasswordStrengthServiceAbstraction } from "@bitwarden/common/tools/password-strength";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
import { flagEnabled } from "../../../utils/flags";
|
||||
@@ -71,6 +73,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
ssoLoginService: SsoLoginServiceAbstraction,
|
||||
webAuthnLoginService: WebAuthnLoginServiceAbstraction,
|
||||
registerRouteService: RegisterRouteService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
devicesApiService,
|
||||
@@ -92,6 +95,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
ssoLoginService,
|
||||
webAuthnLoginService,
|
||||
registerRouteService,
|
||||
toastService,
|
||||
);
|
||||
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
|
||||
this.showPasswordless = flagEnabled("showPasswordless");
|
||||
@@ -138,7 +142,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
async goAfterLogIn() {
|
||||
async goAfterLogIn(userId: UserId) {
|
||||
const masterPassword = this.formGroup.value.masterPassword;
|
||||
|
||||
// Check master password against policy
|
||||
@@ -159,7 +163,7 @@ export class LoginComponent extends BaseLoginComponent implements OnInit {
|
||||
) {
|
||||
const policiesData: { [id: string]: PolicyData } = {};
|
||||
this.policies.map((p) => (policiesData[p.id] = PolicyData.fromPolicy(p)));
|
||||
await this.policyService.replace(policiesData);
|
||||
await this.policyService.replace(policiesData, userId);
|
||||
await this.router.navigate(["update-password"]);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
import { UserKeyRotationModule } from "../key-rotation/user-key-rotation.module";
|
||||
@@ -35,6 +36,7 @@ export class MigrateFromLegacyEncryptionComponent {
|
||||
private messagingService: MessagingService,
|
||||
private logService: LogService,
|
||||
private syncService: SyncService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
submit = async () => {
|
||||
@@ -59,12 +61,12 @@ export class MigrateFromLegacyEncryptionComponent {
|
||||
|
||||
await this.keyRotationService.rotateUserKeyAndEncryptedData(masterPassword, activeUser);
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("keyUpdated"),
|
||||
this.i18nService.t("logBackInOthersToo"),
|
||||
{ timeout: 15000 },
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("keyUpdated"),
|
||||
message: this.i18nService.t("logBackInOthersToo"),
|
||||
timeout: 15000,
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -6,6 +6,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { DeleteRecoverRequest } from "@bitwarden/common/models/request/delete-recover.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-recover-delete",
|
||||
@@ -25,6 +26,7 @@ export class RecoverDeleteComponent {
|
||||
private apiService: ApiService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
submit = async () => {
|
||||
@@ -35,11 +37,11 @@ export class RecoverDeleteComponent {
|
||||
const request = new DeleteRecoverRequest();
|
||||
request.email = this.email.value.trim().toLowerCase();
|
||||
await this.apiService.postAccountRecoverDelete(request);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("deleteRecoverEmailSent"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("deleteRecoverEmailSent"),
|
||||
});
|
||||
|
||||
await this.router.navigate(["/"]);
|
||||
};
|
||||
|
||||
@@ -8,6 +8,7 @@ import { TwoFactorRecoveryRequest } from "@bitwarden/common/auth/models/request/
|
||||
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 { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-recover-two-factor",
|
||||
@@ -27,6 +28,7 @@ export class RecoverTwoFactorComponent {
|
||||
private i18nService: I18nService,
|
||||
private cryptoService: CryptoService,
|
||||
private loginStrategyService: LoginStrategyServiceAbstraction,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
get email(): string {
|
||||
@@ -53,11 +55,11 @@ export class RecoverTwoFactorComponent {
|
||||
const key = await this.loginStrategyService.makePreloginKey(this.masterPassword, request.email);
|
||||
request.masterPasswordHash = await this.cryptoService.hashMasterKey(this.masterPassword, key);
|
||||
await this.apiService.postTwoFactorRecover(request);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("twoStepRecoverDisabled"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("twoStepRecoverDisabled"),
|
||||
});
|
||||
await this.router.navigate(["/"]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
import { AcceptOrganizationInviteService } from "../organization-invite/accept-organization.service";
|
||||
@@ -52,6 +52,7 @@ export class RegisterFormComponent extends BaseRegisterComponent implements OnIn
|
||||
auditService: AuditService,
|
||||
dialogService: DialogService,
|
||||
acceptOrgInviteService: AcceptOrganizationInviteService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
formValidationErrorService,
|
||||
@@ -68,6 +69,7 @@ export class RegisterFormComponent extends BaseRegisterComponent implements OnIn
|
||||
logService,
|
||||
auditService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
super.modifyRegisterRequest = async (request: RegisterRequest) => {
|
||||
// Org invites are deep linked. Non-existent accounts are redirected to the register page.
|
||||
@@ -104,11 +106,11 @@ export class RegisterFormComponent extends BaseRegisterComponent implements OnIn
|
||||
this.enforcedPolicyOptions,
|
||||
)
|
||||
) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("masterPasswordPolicyRequirementsNotMet"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("masterPasswordPolicyRequirementsNotMet"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { ProfileResponse } from "@bitwarden/common/models/response/profile.respo
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
type ChangeAvatarDialogData = {
|
||||
profile: ProfileResponse;
|
||||
@@ -55,6 +55,7 @@ export class ChangeAvatarDialogComponent implements OnInit, OnDestroy {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private avatarService: AvatarService,
|
||||
private dialogRef: DialogRef,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.profile = data.profile;
|
||||
}
|
||||
@@ -93,9 +94,17 @@ export class ChangeAvatarDialogComponent implements OnInit, OnDestroy {
|
||||
if (Utils.validateHexColor(this.currentSelection) || this.currentSelection == null) {
|
||||
await this.avatarService.setAvatarColor(this.currentSelection);
|
||||
this.dialogRef.close();
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("avatarUpdated"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("avatarUpdated"),
|
||||
});
|
||||
} else {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("errorOccurred"),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-change-email",
|
||||
@@ -39,6 +40,7 @@ export class ChangeEmailComponent implements OnInit {
|
||||
private stateService: StateService,
|
||||
private formBuilder: FormBuilder,
|
||||
private kdfConfigService: KdfConfigService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -100,11 +102,11 @@ export class ChangeEmailComponent implements OnInit {
|
||||
try {
|
||||
await this.apiService.postEmail(request);
|
||||
this.reset();
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("emailChanged"),
|
||||
this.i18nService.t("logBackIn"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("emailChanged"),
|
||||
message: this.i18nService.t("logBackIn"),
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -7,6 +7,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-deauthorize-sessions",
|
||||
@@ -23,6 +24,7 @@ export class DeauthorizeSessionsComponent {
|
||||
private userVerificationService: UserVerificationService,
|
||||
private messagingService: MessagingService,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async submit() {
|
||||
@@ -31,11 +33,11 @@ export class DeauthorizeSessionsComponent {
|
||||
.buildRequest(this.masterPassword)
|
||||
.then((request) => this.apiService.postSecurityStamp(request));
|
||||
await this.formPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("sessionsDeauthorized"),
|
||||
this.i18nService.t("logBackIn"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("sessionsDeauthorized"),
|
||||
message: this.i18nService.t("logBackIn"),
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Verification } from "@bitwarden/common/auth/types/verification";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
templateUrl: "delete-account-dialog.component.html",
|
||||
@@ -24,6 +24,7 @@ export class DeleteAccountDialogComponent {
|
||||
private formBuilder: FormBuilder,
|
||||
private accountApiService: AccountApiService,
|
||||
private dialogRef: DialogRef,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
submit = async () => {
|
||||
@@ -31,11 +32,11 @@ export class DeleteAccountDialogComponent {
|
||||
const verification = this.deleteForm.get("verification").value;
|
||||
await this.accountApiService.deleteAccount(verification);
|
||||
this.dialogRef.close();
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("accountDeleted"),
|
||||
this.i18nService.t("accountDeletedDesc"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("accountDeleted"),
|
||||
message: this.i18nService.t("accountDeletedDesc"),
|
||||
});
|
||||
} catch (e) {
|
||||
if (e instanceof ErrorResponse && e.statusCode === 400) {
|
||||
this.invalidSecret = true;
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ProfileResponse } from "@bitwarden/common/models/response/profile.respo
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { ChangeAvatarDialogComponent } from "./change-avatar-dialog.component";
|
||||
|
||||
@@ -33,6 +33,7 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private stateService: StateService,
|
||||
private dialogService: DialogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -64,6 +65,10 @@ export class ProfileComponent implements OnInit, OnDestroy {
|
||||
submit = async () => {
|
||||
const request = new UpdateProfileRequest(this.formGroup.get("name").value);
|
||||
await this.apiService.putProfile(request);
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("accountUpdated"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("accountUpdated"),
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import { UserId } from "@bitwarden/common/types/guid";
|
||||
import { MasterKey, UserKey } from "@bitwarden/common/types/key";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
import { UserKeyRotationService } from "../key-rotation/user-key-rotation.service";
|
||||
@@ -60,6 +60,7 @@ export class ChangePasswordComponent
|
||||
kdfConfigService: KdfConfigService,
|
||||
masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
accountService: AccountService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -73,6 +74,7 @@ export class ChangePasswordComponent
|
||||
kdfConfigService,
|
||||
masterPasswordService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -141,11 +143,11 @@ export class ChangePasswordComponent
|
||||
this.masterPasswordHint != null &&
|
||||
this.masterPasswordHint.toLowerCase() === this.masterPassword.toLowerCase()
|
||||
) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("hintEqualsPassword"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("hintEqualsPassword"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -159,11 +161,11 @@ export class ChangePasswordComponent
|
||||
|
||||
async setupSubmitActions() {
|
||||
if (this.currentMasterPassword == null || this.currentMasterPassword === "") {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("masterPasswordRequired"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("masterPasswordRequired"),
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -194,11 +196,11 @@ export class ChangePasswordComponent
|
||||
|
||||
const userKey = await this.masterPasswordService.decryptUserKeyWithMasterKey(masterKey);
|
||||
if (userKey == null) {
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
null,
|
||||
this.i18nService.t("invalidMasterPassword"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("invalidMasterPassword"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -225,14 +227,18 @@ export class ChangePasswordComponent
|
||||
|
||||
await this.formPromise;
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("masterPasswordChanged"),
|
||||
this.i18nService.t("logBackIn"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("masterPasswordChanged"),
|
||||
message: this.i18nService.t("logBackIn"),
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
} catch {
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("errorOccurred"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("errorOccurred"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { FormBuilder, Validators } from "@angular/forms";
|
||||
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 { EmergencyAccessService } from "../../emergency-access";
|
||||
import { EmergencyAccessType } from "../../emergency-access/enums/emergency-access-type";
|
||||
@@ -51,6 +51,7 @@ export class EmergencyAccessAddEditComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private logService: LogService,
|
||||
private dialogRef: DialogRef<EmergencyAccessAddEditDialogResult>,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
async ngOnInit() {
|
||||
this.editMode = this.loading = this.params.emergencyAccessId != null;
|
||||
@@ -104,11 +105,14 @@ export class EmergencyAccessAddEditComponent implements OnInit {
|
||||
this.addEditForm.value.waitTime,
|
||||
);
|
||||
}
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t(this.editMode ? "editedUserId" : "invitedUsers", this.params.name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t(
|
||||
this.editMode ? "editedUserId" : "invitedUsers",
|
||||
this.params.name,
|
||||
),
|
||||
});
|
||||
this.dialogRef.close(EmergencyAccessAddEditDialogResult.Saved);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
|
||||
@@ -10,7 +10,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { EmergencyAccessService } from "../../emergency-access";
|
||||
import { EmergencyAccessStatusType } from "../../emergency-access/enums/emergency-access-status-type";
|
||||
@@ -66,6 +66,7 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
protected dialogService: DialogService,
|
||||
billingAccountProfileStateService: BillingAccountProfileStateService,
|
||||
protected organizationManagementPreferencesService: OrganizationManagementPreferencesService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.canAccessPremium$ = billingAccountProfileStateService.hasPremiumFromAnySource$;
|
||||
}
|
||||
@@ -121,11 +122,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
}
|
||||
this.actionPromise = this.emergencyAccessService.reinvite(contact.id);
|
||||
await this.actionPromise;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("hasBeenReinvited", contact.email),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("hasBeenReinvited", contact.email),
|
||||
});
|
||||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
@@ -153,11 +154,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
if (result === EmergencyAccessConfirmDialogResult.Confirmed) {
|
||||
await this.emergencyAccessService.confirm(contact.id, contact.granteeId);
|
||||
updateUser();
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(contact)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(contact)),
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -166,11 +167,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
await this.actionPromise;
|
||||
updateUser();
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(contact)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("hasBeenConfirmed", this.userNamePipe.transform(contact)),
|
||||
});
|
||||
this.actionPromise = null;
|
||||
}
|
||||
|
||||
@@ -187,11 +188,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
|
||||
try {
|
||||
await this.emergencyAccessService.delete(details.id);
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("removedUserId", this.userNamePipe.transform(details)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("removedUserId", this.userNamePipe.transform(details)),
|
||||
});
|
||||
|
||||
if (details instanceof GranteeEmergencyAccess) {
|
||||
this.removeGrantee(details);
|
||||
@@ -221,11 +222,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
await this.emergencyAccessService.requestAccess(details.id);
|
||||
|
||||
details.status = EmergencyAccessStatusType.RecoveryInitiated;
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("requestSent", this.userNamePipe.transform(details)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("requestSent", this.userNamePipe.transform(details)),
|
||||
});
|
||||
}
|
||||
|
||||
async approve(details: GranteeEmergencyAccess) {
|
||||
@@ -250,22 +251,22 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
await this.emergencyAccessService.approve(details.id);
|
||||
details.status = EmergencyAccessStatusType.RecoveryApproved;
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("emergencyApproved", this.userNamePipe.transform(details)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("emergencyApproved", this.userNamePipe.transform(details)),
|
||||
});
|
||||
}
|
||||
|
||||
async reject(details: GranteeEmergencyAccess) {
|
||||
await this.emergencyAccessService.reject(details.id);
|
||||
details.status = EmergencyAccessStatusType.Confirmed;
|
||||
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("emergencyRejected", this.userNamePipe.transform(details)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("emergencyRejected", this.userNamePipe.transform(details)),
|
||||
});
|
||||
}
|
||||
|
||||
takeover = async (details: GrantorEmergencyAccess) => {
|
||||
@@ -278,11 +279,11 @@ export class EmergencyAccessComponent implements OnInit {
|
||||
});
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
if (result === EmergencyAccessTakeoverResultType.Done) {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("passwordResetFor", this.userNamePipe.transform(details)),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("passwordResetFor", this.userNamePipe.transform(details)),
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
import { EmergencyAccessService } from "../../../emergency-access";
|
||||
@@ -64,6 +64,7 @@ export class EmergencyAccessTakeoverComponent
|
||||
kdfConfigService: KdfConfigService,
|
||||
masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
accountService: AccountService,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
i18nService,
|
||||
@@ -77,6 +78,7 @@ export class EmergencyAccessTakeoverComponent
|
||||
kdfConfigService,
|
||||
masterPasswordService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -114,11 +116,11 @@ export class EmergencyAccessTakeoverComponent
|
||||
);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("errorOccurred"),
|
||||
this.i18nService.t("unexpectedError"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("errorOccurred"),
|
||||
message: this.i18nService.t("unexpectedError"),
|
||||
});
|
||||
}
|
||||
this.dialogRef.close(EmergencyAccessTakeoverResultType.Done);
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { KdfType } from "@bitwarden/common/platform/enums";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-change-kdf-confirmation",
|
||||
@@ -35,6 +36,7 @@ export class ChangeKdfConfirmationComponent {
|
||||
private messagingService: MessagingService,
|
||||
@Inject(DIALOG_DATA) params: { kdf: KdfType; kdfConfig: KdfConfig },
|
||||
private accountService: AccountService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.kdfConfig = params.kdfConfig;
|
||||
this.masterPassword = null;
|
||||
@@ -46,11 +48,11 @@ export class ChangeKdfConfirmationComponent {
|
||||
}
|
||||
this.loading = true;
|
||||
await this.makeKeyAndSaveAsync();
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
this.i18nService.t("encKeySettingsChanged"),
|
||||
this.i18nService.t("logBackIn"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("encKeySettingsChanged"),
|
||||
message: this.i18nService.t("logBackIn"),
|
||||
});
|
||||
this.messagingService.send("logout");
|
||||
this.loading = false;
|
||||
};
|
||||
|
||||
@@ -17,7 +17,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -68,6 +68,7 @@ export class TwoFactorAuthenticatorComponent
|
||||
private accountService: AccountService,
|
||||
dialogService: DialogService,
|
||||
private configService: ConfigService,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -76,6 +77,7 @@ export class TwoFactorAuthenticatorComponent
|
||||
logService,
|
||||
userVerificationService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
this.qrScript = window.document.createElement("script");
|
||||
this.qrScript.src = "scripts/qrious.min.js";
|
||||
@@ -148,7 +150,11 @@ export class TwoFactorAuthenticatorComponent
|
||||
request.userVerificationToken = this.userVerificationToken;
|
||||
await this.apiService.deleteTwoFactorAuthenticator(request);
|
||||
this.enabled = false;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("twoStepDisabled"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("twoStepDisabled"),
|
||||
});
|
||||
this.onUpdated.emit(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import { AuthResponseBase } from "@bitwarden/common/auth/types/auth-response";
|
||||
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";
|
||||
|
||||
@Directive()
|
||||
export abstract class TwoFactorBaseComponent {
|
||||
@@ -33,6 +33,7 @@ export abstract class TwoFactorBaseComponent {
|
||||
protected logService: LogService,
|
||||
protected userVerificationService: UserVerificationService,
|
||||
protected dialogService: DialogService,
|
||||
protected toastService: ToastService,
|
||||
) {}
|
||||
|
||||
protected auth(authResponse: AuthResponseBase) {
|
||||
@@ -76,7 +77,11 @@ export abstract class TwoFactorBaseComponent {
|
||||
}
|
||||
await promise;
|
||||
this.enabled = false;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("twoStepDisabled"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("twoStepDisabled"),
|
||||
});
|
||||
this.onUpdated.emit(false);
|
||||
} catch (e) {
|
||||
this.logService.error(e);
|
||||
@@ -102,7 +107,11 @@ export abstract class TwoFactorBaseComponent {
|
||||
await this.apiService.putTwoFactorDisable(request);
|
||||
}
|
||||
this.enabled = false;
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("twoStepDisabled"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("twoStepDisabled"),
|
||||
});
|
||||
this.onUpdated.emit(false);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
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 { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -40,6 +40,7 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent implements OnI
|
||||
dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -48,6 +49,7 @@ export class TwoFactorDuoComponent extends TwoFactorBaseComponent implements OnI
|
||||
logService,
|
||||
userVerificationService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
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 { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -45,6 +45,7 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent implements O
|
||||
dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private dialogRef: DialogRef,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -53,6 +54,7 @@ export class TwoFactorEmailComponent extends TwoFactorBaseComponent implements O
|
||||
logService,
|
||||
userVerificationService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
get token() {
|
||||
|
||||
@@ -16,7 +16,7 @@ import { AuthResponse } from "@bitwarden/common/auth/types/auth-response";
|
||||
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 { TwoFactorBaseComponent } from "./two-factor-base.component";
|
||||
|
||||
@@ -61,6 +61,7 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent {
|
||||
logService: LogService,
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -69,6 +70,7 @@ export class TwoFactorWebAuthnComponent extends TwoFactorBaseComponent {
|
||||
logService,
|
||||
userVerificationService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
this.auth(data);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent implements
|
||||
userVerificationService: UserVerificationService,
|
||||
dialogService: DialogService,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
protected toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
apiService,
|
||||
@@ -64,6 +64,7 @@ export class TwoFactorYubiKeyComponent extends TwoFactorBaseComponent implements
|
||||
logService,
|
||||
userVerificationService,
|
||||
dialogService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,13 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { AsyncActionsModule, BannerModule, ButtonModule, LinkModule } from "@bitwarden/components";
|
||||
import {
|
||||
AsyncActionsModule,
|
||||
BannerModule,
|
||||
ButtonModule,
|
||||
LinkModule,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
@@ -25,22 +31,27 @@ export class VerifyEmailComponent {
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private tokenService: TokenService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async verifyEmail(): Promise<void> {
|
||||
await this.apiService.refreshIdentityToken();
|
||||
if (await this.tokenService.getEmailVerified()) {
|
||||
this.onVerified.emit(true);
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("emailVerified"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("emailVerified"),
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await this.apiService.postAccountVerifyEmail();
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("checkInboxForVerification"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("checkInboxForVerification"),
|
||||
});
|
||||
}
|
||||
|
||||
send = async () => {
|
||||
|
||||
@@ -9,7 +9,7 @@ import { ErrorResponse } from "@bitwarden/common/models/response/error.response"
|
||||
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 { WebauthnLoginAdminService } from "../../../core";
|
||||
import { CredentialCreateOptionsView } from "../../../core/views/credential-create-options.view";
|
||||
@@ -60,6 +60,7 @@ export class CreateCredentialDialogComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -102,11 +103,11 @@ export class CreateCredentialDialogComponent implements OnInit {
|
||||
this.invalidSecret = true;
|
||||
} else {
|
||||
this.logService?.error(error);
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("unexpectedError"),
|
||||
error.message,
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("unexpectedError"),
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -162,17 +163,17 @@ export class CreateCredentialDialogComponent implements OnInit {
|
||||
);
|
||||
|
||||
if (await firstValueFrom(this.hasPasskeys$)) {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("passkeySaved", name),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("passkeySaved", name),
|
||||
});
|
||||
} else {
|
||||
this.platformUtilsService.showToast(
|
||||
"success",
|
||||
null,
|
||||
this.i18nService.t("loginWithPasskeyEnabled"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("loginWithPasskeyEnabled"),
|
||||
});
|
||||
}
|
||||
|
||||
this.dialogRef.close(CreateCredentialDialogResult.Success);
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ErrorResponse } from "@bitwarden/common/models/response/error.response"
|
||||
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 { WebauthnLoginAdminService } from "../../../core";
|
||||
import { WebauthnLoginCredentialView } from "../../../core/views/webauthn-login-credential.view";
|
||||
@@ -38,6 +38,7 @@ export class DeleteCredentialDialogComponent implements OnInit, OnDestroy {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private logService: LogService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
@@ -55,17 +56,21 @@ export class DeleteCredentialDialogComponent implements OnInit, OnDestroy {
|
||||
this.dialogRef.disableClose = true;
|
||||
try {
|
||||
await this.webauthnService.deleteCredential(this.credential.id, this.formGroup.value.secret);
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("passkeyRemoved"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("passkeyRemoved"),
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof ErrorResponse && error.statusCode === 400) {
|
||||
this.invalidSecret = true;
|
||||
} else {
|
||||
this.logService?.error(error);
|
||||
this.platformUtilsService.showToast(
|
||||
"error",
|
||||
this.i18nService.t("unexpectedError"),
|
||||
error.message,
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: this.i18nService.t("unexpectedError"),
|
||||
message: error.message,
|
||||
});
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
import { UserVerificationService } from "@bitwarden/common/auth/abstractions/user-verification/user-verification.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
/**
|
||||
* @deprecated Jan 24, 2024: Use new libs/auth UserVerificationDialogComponent instead.
|
||||
@@ -25,8 +25,17 @@ export class UserVerificationPromptComponent extends BaseUserVerificationPrompt
|
||||
formBuilder: FormBuilder,
|
||||
platformUtilsService: PlatformUtilsService,
|
||||
i18nService: I18nService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(null, data, userVerificationService, formBuilder, platformUtilsService, i18nService);
|
||||
super(
|
||||
null,
|
||||
data,
|
||||
userVerificationService,
|
||||
formBuilder,
|
||||
platformUtilsService,
|
||||
i18nService,
|
||||
toastService,
|
||||
);
|
||||
}
|
||||
|
||||
override close(success: boolean) {
|
||||
|
||||
@@ -25,6 +25,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ValidationService } from "@bitwarden/common/platform/abstractions/validation.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
import { PasswordGenerationServiceAbstraction } from "@bitwarden/generator-legacy";
|
||||
|
||||
@Component({
|
||||
@@ -60,6 +61,7 @@ export class SsoComponent extends BaseSsoComponent implements OnInit {
|
||||
configService: ConfigService,
|
||||
masterPasswordService: InternalMasterPasswordServiceAbstraction,
|
||||
accountService: AccountService,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
ssoLoginService,
|
||||
@@ -78,6 +80,7 @@ export class SsoComponent extends BaseSsoComponent implements OnInit {
|
||||
configService,
|
||||
masterPasswordService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
this.redirectUri = window.location.origin + "/sso-connector.html";
|
||||
this.clientId = "web";
|
||||
|
||||
@@ -17,7 +17,13 @@ import { EnvironmentService } from "@bitwarden/common/platform/abstractions/envi
|
||||
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 { LinkModule, TypographyModule, CheckboxModule, DialogService } from "@bitwarden/components";
|
||||
import {
|
||||
LinkModule,
|
||||
TypographyModule,
|
||||
CheckboxModule,
|
||||
DialogService,
|
||||
ToastService,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { TwoFactorAuthAuthenticatorComponent } from "../../../../../libs/angular/src/auth/components/two-factor-auth/two-factor-auth-authenticator.component";
|
||||
import { TwoFactorAuthEmailComponent } from "../../../../../libs/angular/src/auth/components/two-factor-auth/two-factor-auth-email.component";
|
||||
@@ -81,6 +87,7 @@ export class TwoFactorAuthComponent extends BaseTwoFactorAuthComponent {
|
||||
accountService: AccountService,
|
||||
formBuilder: FormBuilder,
|
||||
@Inject(WINDOW) protected win: Window,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
loginStrategyService,
|
||||
@@ -100,6 +107,7 @@ export class TwoFactorAuthComponent extends BaseTwoFactorAuthComponent {
|
||||
accountService,
|
||||
formBuilder,
|
||||
win,
|
||||
toastService,
|
||||
);
|
||||
this.onSuccessfulLoginNavigate = this.goAfterLogIn;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-verify-email-token",
|
||||
@@ -23,6 +24,7 @@ export class VerifyEmailTokenComponent implements OnInit {
|
||||
private apiService: ApiService,
|
||||
private logService: LogService,
|
||||
private stateService: StateService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -36,7 +38,11 @@ export class VerifyEmailTokenComponent implements OnInit {
|
||||
if (await this.stateService.getIsAuthenticated()) {
|
||||
await this.apiService.refreshIdentityToken();
|
||||
}
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("emailVerified"));
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("emailVerified"),
|
||||
});
|
||||
// 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(["/"]);
|
||||
@@ -45,7 +51,11 @@ export class VerifyEmailTokenComponent implements OnInit {
|
||||
this.logService.error(e);
|
||||
}
|
||||
}
|
||||
this.platformUtilsService.showToast("error", null, this.i18nService.t("emailVerifiedFailed"));
|
||||
this.toastService.showToast({
|
||||
variant: "error",
|
||||
title: null,
|
||||
message: this.i18nService.t("emailVerifiedFailed"),
|
||||
});
|
||||
// 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(["/"]);
|
||||
|
||||
@@ -7,6 +7,7 @@ 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 { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-verify-recover-delete",
|
||||
@@ -26,6 +27,7 @@ export class VerifyRecoverDeleteComponent implements OnInit {
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private i18nService: I18nService,
|
||||
private route: ActivatedRoute,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
@@ -44,11 +46,11 @@ export class VerifyRecoverDeleteComponent implements OnInit {
|
||||
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"),
|
||||
);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: this.i18nService.t("accountDeleted"),
|
||||
message: this.i18nService.t("accountDeletedDesc"),
|
||||
});
|
||||
await this.router.navigate(["/"]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -56,4 +56,3 @@
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
<app-payment [showMethods]="false"></app-payment>
|
||||
|
||||
@@ -1,43 +1,36 @@
|
||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
import { Subject, takeUntil } from "rxjs";
|
||||
|
||||
import { OrganizationApiServiceAbstraction } from "@bitwarden/common/admin-console/abstractions/organization/organization-api.service.abstraction";
|
||||
import { OrganizationSubscriptionUpdateRequest } from "@bitwarden/common/billing/models/request/organization-subscription-update.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-adjust-subscription",
|
||||
templateUrl: "adjust-subscription.component.html",
|
||||
})
|
||||
export class AdjustSubscription implements OnInit, OnDestroy {
|
||||
export class AdjustSubscription {
|
||||
@Input() organizationId: string;
|
||||
@Input() maxAutoscaleSeats: number;
|
||||
@Input() currentSeatCount: number;
|
||||
@Input() seatPrice = 0;
|
||||
@Input() interval = "year";
|
||||
@Output() onAdjusted = new EventEmitter();
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
adjustSubscriptionForm = this.formBuilder.group({
|
||||
newSeatCount: [0, [Validators.min(0)]],
|
||||
limitSubscription: [false],
|
||||
newMaxSeats: [0, [Validators.min(0)]],
|
||||
});
|
||||
get limitSubscription(): boolean {
|
||||
return this.adjustSubscriptionForm.value.limitSubscription;
|
||||
}
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private formBuilder: FormBuilder,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
) {
|
||||
this.adjustSubscriptionForm.patchValue({
|
||||
newSeatCount: this.currentSeatCount,
|
||||
limitSubscription: this.maxAutoscaleSeats != null,
|
||||
@@ -45,7 +38,7 @@ export class AdjustSubscription implements OnInit, OnDestroy {
|
||||
});
|
||||
this.adjustSubscriptionForm
|
||||
.get("limitSubscription")
|
||||
.valueChanges.pipe(takeUntil(this.destroy$))
|
||||
.valueChanges.pipe(takeUntilDestroyed())
|
||||
.subscribe((value: boolean) => {
|
||||
if (value) {
|
||||
this.adjustSubscriptionForm
|
||||
@@ -63,10 +56,6 @@ export class AdjustSubscription implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
}
|
||||
submit = async () => {
|
||||
this.adjustSubscriptionForm.markAllAsTouched();
|
||||
if (this.adjustSubscriptionForm.invalid) {
|
||||
@@ -99,18 +88,15 @@ export class AdjustSubscription implements OnInit, OnDestroy {
|
||||
: 0;
|
||||
}
|
||||
|
||||
get additionalMaxSeatCount(): number {
|
||||
return this.adjustSubscriptionForm.value.newMaxSeats
|
||||
? this.adjustSubscriptionForm.value.newMaxSeats - this.currentSeatCount
|
||||
: 0;
|
||||
}
|
||||
|
||||
get maxSeatTotal(): number {
|
||||
return Math.abs((this.adjustSubscriptionForm.value.newMaxSeats ?? 0) * this.seatPrice);
|
||||
}
|
||||
|
||||
get seatTotalCost(): number {
|
||||
const totalSeat = Math.abs(this.adjustSubscriptionForm.value.newSeatCount * this.seatPrice);
|
||||
return totalSeat;
|
||||
return Math.abs(this.adjustSubscriptionForm.value.newSeatCount * this.seatPrice);
|
||||
}
|
||||
|
||||
get limitSubscription(): boolean {
|
||||
return this.adjustSubscriptionForm.value.limitSubscription;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
bitIconButton="bwi-clone"
|
||||
bitSuffix
|
||||
type="button"
|
||||
showToast
|
||||
[valueLabel]="'billingSyncKey' | i18n"
|
||||
[appCopyClick]="clientSecret"
|
||||
[appA11yTitle]="'copyValue' | i18n"
|
||||
></button>
|
||||
|
||||
@@ -37,7 +37,7 @@ import { MessagingService } from "@bitwarden/common/platform/abstractions/messag
|
||||
import { SyncService } from "@bitwarden/common/vault/abstractions/sync/sync.service.abstraction";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { PaymentComponent } from "../shared/payment.component";
|
||||
import { PaymentComponent } from "../shared/payment/payment.component";
|
||||
import { TaxInfoComponent } from "../shared/tax-info.component";
|
||||
|
||||
type ChangePlanDialogParams = {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule, Routes } from "@angular/router";
|
||||
|
||||
import { featureFlaggedRoute } from "@bitwarden/angular/platform/utils/feature-flagged-route";
|
||||
import { canAccessBillingTab } from "@bitwarden/common/admin-console/abstractions/organization/organization.service.abstraction";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
import { organizationPermissionsGuard } from "../../admin-console/organizations/guards/org-permissions.guard";
|
||||
import { organizationIsUnmanaged } from "../../billing/guards/organization-is-unmanaged.guard";
|
||||
@@ -11,6 +13,7 @@ import { PaymentMethodComponent } from "../shared";
|
||||
import { OrgBillingHistoryViewComponent } from "./organization-billing-history-view.component";
|
||||
import { OrganizationSubscriptionCloudComponent } from "./organization-subscription-cloud.component";
|
||||
import { OrganizationSubscriptionSelfhostComponent } from "./organization-subscription-selfhost.component";
|
||||
import { OrganizationPaymentMethodComponent } from "./payment-method/organization-payment-method.component";
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@@ -25,17 +28,21 @@ const routes: Routes = [
|
||||
: OrganizationSubscriptionCloudComponent,
|
||||
data: { titleId: "subscription" },
|
||||
},
|
||||
{
|
||||
path: "payment-method",
|
||||
component: PaymentMethodComponent,
|
||||
canActivate: [
|
||||
organizationPermissionsGuard((org) => org.canEditPaymentMethods),
|
||||
organizationIsUnmanaged,
|
||||
],
|
||||
data: {
|
||||
titleId: "paymentMethod",
|
||||
...featureFlaggedRoute({
|
||||
defaultComponent: PaymentMethodComponent,
|
||||
flaggedComponent: OrganizationPaymentMethodComponent,
|
||||
featureFlag: FeatureFlag.AC2476_DeprecateStripeSourcesAPI,
|
||||
routeOptions: {
|
||||
path: "payment-method",
|
||||
canActivate: [
|
||||
organizationPermissionsGuard((org) => org.canEditPaymentMethods),
|
||||
organizationIsUnmanaged,
|
||||
],
|
||||
data: {
|
||||
titleId: "paymentMethod",
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
{
|
||||
path: "history",
|
||||
component: OrgBillingHistoryViewComponent,
|
||||
|
||||
@@ -15,6 +15,7 @@ import { OrganizationBillingRoutingModule } from "./organization-billing-routing
|
||||
import { OrganizationPlansComponent } from "./organization-plans.component";
|
||||
import { OrganizationSubscriptionCloudComponent } from "./organization-subscription-cloud.component";
|
||||
import { OrganizationSubscriptionSelfhostComponent } from "./organization-subscription-selfhost.component";
|
||||
import { OrganizationPaymentMethodComponent } from "./payment-method/organization-payment-method.component";
|
||||
import { SecretsManagerAdjustSubscriptionComponent } from "./sm-adjust-subscription.component";
|
||||
import { SecretsManagerSubscribeStandaloneComponent } from "./sm-subscribe-standalone.component";
|
||||
import { SubscriptionHiddenComponent } from "./subscription-hidden.component";
|
||||
@@ -42,6 +43,7 @@ import { SubscriptionStatusComponent } from "./subscription-status.component";
|
||||
SubscriptionHiddenComponent,
|
||||
SubscriptionStatusComponent,
|
||||
ChangePlanDialogComponent,
|
||||
OrganizationPaymentMethodComponent,
|
||||
],
|
||||
})
|
||||
export class OrganizationBillingModule {}
|
||||
|
||||
@@ -41,7 +41,7 @@ import { ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationCreateModule } from "../../admin-console/organizations/create/organization-create.module";
|
||||
import { BillingSharedModule, secretsManagerSubscribeFormFactory } from "../shared";
|
||||
import { PaymentComponent } from "../shared/payment.component";
|
||||
import { PaymentComponent } from "../shared/payment/payment.component";
|
||||
import { TaxInfoComponent } from "../shared/tax-info.component";
|
||||
|
||||
interface OnSuccessArgs {
|
||||
|
||||
@@ -222,8 +222,10 @@
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
<h2 bitTypography="h2" class="tw-mt-7">{{ "selfHostingTitle" | i18n }}</h2>
|
||||
<p bitTypography="body1">
|
||||
<h2 bitTypography="h2" *ngIf="shownSelfHost()" class="tw-mt-7">
|
||||
{{ "selfHostingTitle" | i18n }}
|
||||
</h2>
|
||||
<p bitTypography="body1" *ngIf="shownSelfHost()">
|
||||
{{ "selfHostingEnterpriseOrganizationSectionCopy" | i18n }}
|
||||
<a
|
||||
href="https://bitwarden.com/help/licensing-on-premise/#retrieve-organization-license"
|
||||
@@ -240,7 +242,7 @@
|
||||
buttonType="secondary"
|
||||
type="button"
|
||||
(click)="downloadLicense()"
|
||||
*ngIf="canDownloadLicense"
|
||||
*ngIf="canDownloadLicense && shownSelfHost()"
|
||||
[disabled]="showDownloadLicense"
|
||||
>
|
||||
{{ "downloadLicense" | i18n }}
|
||||
|
||||
@@ -345,6 +345,13 @@ export class OrganizationSubscriptionCloudComponent implements OnInit, OnDestroy
|
||||
);
|
||||
}
|
||||
|
||||
shownSelfHost(): boolean {
|
||||
return (
|
||||
this.sub?.plan.productTier !== ProductTierType.Teams &&
|
||||
this.sub?.plan.productTier !== ProductTierType.Free
|
||||
);
|
||||
}
|
||||
|
||||
cancelSubscription = async () => {
|
||||
const reference = openOffboardingSurvey(this.dialogService, {
|
||||
data: {
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
<app-header></app-header>
|
||||
<bit-container>
|
||||
<ng-container *ngIf="loading">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!loading">
|
||||
<!-- Account Credit -->
|
||||
<bit-section>
|
||||
<h2 bitTypography="h2">
|
||||
{{ accountCreditHeaderText }}
|
||||
</h2>
|
||||
<p class="tw-text-lg tw-font-bold">{{ Math.abs(accountCredit) | currency: "$" }}</p>
|
||||
<p bitTypography="body1">{{ "creditAppliedDesc" | i18n }}</p>
|
||||
<button type="button" bitButton buttonType="secondary" [bitAction]="addAccountCredit">
|
||||
{{ "addCredit" | i18n }}
|
||||
</button>
|
||||
</bit-section>
|
||||
<!-- Payment Method -->
|
||||
<bit-section>
|
||||
<h2 bitTypography="h2">{{ "paymentMethod" | i18n }}</h2>
|
||||
<p *ngIf="!paymentSource" bitTypography="body1">{{ "noPaymentMethod" | i18n }}</p>
|
||||
<ng-container *ngIf="paymentSource">
|
||||
<app-verify-bank-account
|
||||
*ngIf="paymentSource.needsVerification"
|
||||
[onSubmit]="verifyBankAccount"
|
||||
(submitted)="load()"
|
||||
>
|
||||
</app-verify-bank-account>
|
||||
<p>
|
||||
<i class="bwi bwi-fw" [ngClass]="paymentSourceClasses"></i>
|
||||
{{ paymentSource.description }}
|
||||
<span *ngIf="paymentSource.needsVerification">- {{ "unverified" | i18n }}</span>
|
||||
</p>
|
||||
</ng-container>
|
||||
<button type="button" bitButton buttonType="secondary" [bitAction]="updatePaymentMethod">
|
||||
{{ updatePaymentSourceButtonText }}
|
||||
</button>
|
||||
<p *ngIf="subscriptionIsUnpaid" bitTypography="body1">
|
||||
{{ "paymentChargedWithUnpaidSubscription" | i18n }}
|
||||
</p>
|
||||
</bit-section>
|
||||
<!-- Tax Information -->
|
||||
<bit-section>
|
||||
<h2 bitTypography="h2">{{ "taxInformation" | i18n }}</h2>
|
||||
<p bitTypography="body1">{{ "taxInformationDesc" | i18n }}</p>
|
||||
<app-tax-info></app-tax-info>
|
||||
<button
|
||||
type="button"
|
||||
bitButton
|
||||
bitFormButton
|
||||
buttonType="primary"
|
||||
[bitAction]="updateTaxInformation"
|
||||
>
|
||||
{{ "save" | i18n }}
|
||||
</button>
|
||||
</bit-section>
|
||||
</ng-container>
|
||||
</bit-container>
|
||||
@@ -0,0 +1,169 @@
|
||||
import { Component, ViewChild } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { ActivatedRoute, Router } from "@angular/router";
|
||||
import { from, lastValueFrom, switchMap } from "rxjs";
|
||||
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { ExpandedTaxInfoUpdateRequest } from "@bitwarden/common/billing/models/request/expanded-tax-info-update.request";
|
||||
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
|
||||
import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { TaxInfoComponent } from "../../shared";
|
||||
import {
|
||||
AddCreditDialogResult,
|
||||
openAddCreditDialog,
|
||||
} from "../../shared/add-credit-dialog.component";
|
||||
import {
|
||||
AdjustPaymentDialogV2Component,
|
||||
AdjustPaymentDialogV2ResultType,
|
||||
} from "../../shared/adjust-payment-dialog/adjust-payment-dialog-v2.component";
|
||||
|
||||
@Component({
|
||||
templateUrl: "./organization-payment-method.component.html",
|
||||
})
|
||||
export class OrganizationPaymentMethodComponent {
|
||||
@ViewChild(TaxInfoComponent) taxInfoComponent: TaxInfoComponent;
|
||||
|
||||
organizationId: string;
|
||||
accountCredit: number;
|
||||
paymentSource?: PaymentSourceResponse;
|
||||
subscriptionStatus?: string;
|
||||
|
||||
loading = true;
|
||||
|
||||
protected readonly Math = Math;
|
||||
|
||||
constructor(
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private billingApiService: BillingApiServiceAbstraction,
|
||||
private dialogService: DialogService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService,
|
||||
private router: Router,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
this.activatedRoute.params
|
||||
.pipe(
|
||||
takeUntilDestroyed(),
|
||||
switchMap(({ organizationId }) => {
|
||||
if (this.platformUtilsService.isSelfHost()) {
|
||||
return from(this.router.navigate(["/settings/subscription"]));
|
||||
}
|
||||
|
||||
this.organizationId = organizationId;
|
||||
return from(this.load());
|
||||
}),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
protected addAccountCredit = async (): Promise<void> => {
|
||||
const dialogRef = openAddCreditDialog(this.dialogService, {
|
||||
data: {
|
||||
organizationId: this.organizationId,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
|
||||
if (result === AddCreditDialogResult.Added) {
|
||||
await this.load();
|
||||
}
|
||||
};
|
||||
|
||||
protected load = async (): Promise<void> => {
|
||||
this.loading = true;
|
||||
const { accountCredit, paymentSource, subscriptionStatus } =
|
||||
await this.billingApiService.getOrganizationPaymentMethod(this.organizationId);
|
||||
this.accountCredit = accountCredit;
|
||||
this.paymentSource = paymentSource;
|
||||
this.subscriptionStatus = subscriptionStatus;
|
||||
this.loading = false;
|
||||
};
|
||||
|
||||
protected updatePaymentMethod = async (): Promise<void> => {
|
||||
const dialogRef = AdjustPaymentDialogV2Component.open(this.dialogService, {
|
||||
data: {
|
||||
initialPaymentMethod: this.paymentSource?.type,
|
||||
organizationId: this.organizationId,
|
||||
},
|
||||
});
|
||||
|
||||
const result = await lastValueFrom(dialogRef.closed);
|
||||
|
||||
if (result === AdjustPaymentDialogV2ResultType.Submitted) {
|
||||
await this.load();
|
||||
}
|
||||
};
|
||||
|
||||
protected updateTaxInformation = async (): Promise<void> => {
|
||||
this.taxInfoComponent.taxFormGroup.updateValueAndValidity();
|
||||
this.taxInfoComponent.taxFormGroup.markAllAsTouched();
|
||||
|
||||
if (this.taxInfoComponent.taxFormGroup.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const request = new ExpandedTaxInfoUpdateRequest();
|
||||
request.country = this.taxInfoComponent.country;
|
||||
request.postalCode = this.taxInfoComponent.postalCode;
|
||||
request.taxId = this.taxInfoComponent.taxId;
|
||||
request.line1 = this.taxInfoComponent.line1;
|
||||
request.line2 = this.taxInfoComponent.line2;
|
||||
request.city = this.taxInfoComponent.city;
|
||||
request.state = this.taxInfoComponent.state;
|
||||
|
||||
await this.billingApiService.updateOrganizationTaxInformation(this.organizationId, request);
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("taxInfoUpdated"),
|
||||
});
|
||||
};
|
||||
|
||||
protected verifyBankAccount = async (request: VerifyBankAccountRequest): Promise<void> => {
|
||||
await this.billingApiService.verifyOrganizationBankAccount(this.organizationId, request);
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("verifiedBankAccount"),
|
||||
});
|
||||
};
|
||||
|
||||
protected get accountCreditHeaderText(): string {
|
||||
const key = this.accountCredit <= 0 ? "accountBalance" : "accountCredit";
|
||||
return this.i18nService.t(key);
|
||||
}
|
||||
|
||||
protected get paymentSourceClasses() {
|
||||
if (this.paymentSource == null) {
|
||||
return [];
|
||||
}
|
||||
switch (this.paymentSource.type) {
|
||||
case PaymentMethodType.Card:
|
||||
return ["bwi-credit-card"];
|
||||
case PaymentMethodType.BankAccount:
|
||||
return ["bwi-bank"];
|
||||
case PaymentMethodType.Check:
|
||||
return ["bwi-money"];
|
||||
case PaymentMethodType.PayPal:
|
||||
return ["bwi-paypal text-primary"];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
protected get subscriptionIsUnpaid(): boolean {
|
||||
return this.subscriptionStatus === "unpaid";
|
||||
}
|
||||
|
||||
protected get updatePaymentSourceButtonText(): string {
|
||||
const key = this.paymentSource == null ? "addPaymentMethod" : "changePaymentMethod";
|
||||
return this.i18nService.t(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<bit-dialog dialogSize="large" [title]="dialogHeader">
|
||||
<ng-container bitDialogContent>
|
||||
<app-payment-v2
|
||||
[showAccountCredit]="false"
|
||||
[showBankAccount]="!!organizationId"
|
||||
[initialPaymentMethod]="initialPaymentMethod"
|
||||
></app-payment-v2>
|
||||
<app-tax-info (onCountryChanged)="onCountryChanged()"></app-tax-info>
|
||||
</ng-container>
|
||||
<ng-container bitDialogFooter>
|
||||
<button type="submit" bitButton bitFormButton buttonType="primary" [bitAction]="submit">
|
||||
{{ "submit" }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
bitButton
|
||||
bitFormButton
|
||||
buttonType="secondary"
|
||||
[bitDialogClose]="ResultType.Closed"
|
||||
>
|
||||
{{ "cancel" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</bit-dialog>
|
||||
@@ -0,0 +1,123 @@
|
||||
import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||
import { forwardRef, Component, Inject, ViewChild } from "@angular/core";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { PaymentRequest } from "@bitwarden/common/billing/models/request/payment.request";
|
||||
import { UpdatePaymentMethodRequest } from "@bitwarden/common/billing/models/request/update-payment-method.request";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { TaxInfoComponent } from "../";
|
||||
import { PaymentV2Component } from "../payment/payment-v2.component";
|
||||
|
||||
export interface AdjustPaymentDialogV2Params {
|
||||
initialPaymentMethod?: PaymentMethodType;
|
||||
organizationId?: string;
|
||||
}
|
||||
|
||||
export enum AdjustPaymentDialogV2ResultType {
|
||||
Closed = "closed",
|
||||
Submitted = "submitted",
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: "./adjust-payment-dialog-v2.component.html",
|
||||
})
|
||||
export class AdjustPaymentDialogV2Component {
|
||||
@ViewChild(PaymentV2Component) paymentComponent: PaymentV2Component;
|
||||
@ViewChild(forwardRef(() => TaxInfoComponent)) taxInfoComponent: TaxInfoComponent;
|
||||
|
||||
protected readonly PaymentMethodType = PaymentMethodType;
|
||||
protected readonly ResultType = AdjustPaymentDialogV2ResultType;
|
||||
|
||||
protected dialogHeader: string;
|
||||
protected initialPaymentMethod: PaymentMethodType;
|
||||
protected organizationId?: string;
|
||||
|
||||
constructor(
|
||||
private apiService: ApiService,
|
||||
private billingApiService: BillingApiServiceAbstraction,
|
||||
@Inject(DIALOG_DATA) protected dialogParams: AdjustPaymentDialogV2Params,
|
||||
private dialogRef: DialogRef<AdjustPaymentDialogV2ResultType>,
|
||||
private i18nService: I18nService,
|
||||
private toastService: ToastService,
|
||||
) {
|
||||
const key = this.dialogParams.initialPaymentMethod ? "changePaymentMethod" : "addPaymentMethod";
|
||||
this.dialogHeader = this.i18nService.t(key);
|
||||
this.initialPaymentMethod = this.dialogParams.initialPaymentMethod ?? PaymentMethodType.Card;
|
||||
this.organizationId = this.dialogParams.organizationId;
|
||||
}
|
||||
|
||||
onCountryChanged = () => {
|
||||
if (this.taxInfoComponent.taxInfo.country === "US") {
|
||||
this.paymentComponent.showBankAccount = !!this.organizationId;
|
||||
} else {
|
||||
this.paymentComponent.showBankAccount = false;
|
||||
if (this.paymentComponent.selected === PaymentMethodType.BankAccount) {
|
||||
this.paymentComponent.select(PaymentMethodType.Card);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
submit = async (): Promise<void> => {
|
||||
this.taxInfoComponent.taxFormGroup.updateValueAndValidity();
|
||||
this.taxInfoComponent.taxFormGroup.markAllAsTouched();
|
||||
if (this.taxInfoComponent.taxFormGroup.invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.organizationId) {
|
||||
await this.updatePremiumUserPaymentMethod();
|
||||
} else {
|
||||
await this.updateOrganizationPaymentMethod();
|
||||
}
|
||||
|
||||
this.toastService.showToast({
|
||||
variant: "success",
|
||||
title: null,
|
||||
message: this.i18nService.t("updatedPaymentMethod"),
|
||||
});
|
||||
|
||||
this.dialogRef.close(AdjustPaymentDialogV2ResultType.Submitted);
|
||||
};
|
||||
|
||||
private updateOrganizationPaymentMethod = async () => {
|
||||
const paymentSource = await this.paymentComponent.tokenize();
|
||||
|
||||
const request = new UpdatePaymentMethodRequest();
|
||||
request.paymentSource = paymentSource;
|
||||
request.taxInformation = {
|
||||
country: this.taxInfoComponent.country,
|
||||
postalCode: this.taxInfoComponent.postalCode,
|
||||
taxId: this.taxInfoComponent.taxId,
|
||||
line1: this.taxInfoComponent.line1,
|
||||
line2: this.taxInfoComponent.line2,
|
||||
city: this.taxInfoComponent.city,
|
||||
state: this.taxInfoComponent.state,
|
||||
};
|
||||
|
||||
await this.billingApiService.updateOrganizationPaymentMethod(this.organizationId, request);
|
||||
};
|
||||
|
||||
private updatePremiumUserPaymentMethod = async () => {
|
||||
const { type, token } = await this.paymentComponent.tokenize();
|
||||
|
||||
const request = new PaymentRequest();
|
||||
request.paymentMethodType = type;
|
||||
request.paymentToken = token;
|
||||
request.country = this.taxInfoComponent.country;
|
||||
request.postalCode = this.taxInfoComponent.postalCode;
|
||||
await this.apiService.postAccountPayment(request);
|
||||
};
|
||||
|
||||
static open = (
|
||||
dialogService: DialogService,
|
||||
dialogConfig: DialogConfig<AdjustPaymentDialogV2Params>,
|
||||
) =>
|
||||
dialogService.open<AdjustPaymentDialogV2ResultType>(
|
||||
AdjustPaymentDialogV2Component,
|
||||
dialogConfig,
|
||||
);
|
||||
}
|
||||
@@ -10,8 +10,8 @@ import { ConfigService } from "@bitwarden/common/platform/abstractions/config/co
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { PaymentComponent } from "./payment.component";
|
||||
import { TaxInfoComponent } from "./tax-info.component";
|
||||
import { PaymentComponent } from "../payment/payment.component";
|
||||
import { TaxInfoComponent } from "../tax-info.component";
|
||||
|
||||
export interface AdjustPaymentDialogData {
|
||||
organizationId: string;
|
||||
@@ -12,7 +12,7 @@ import { LogService } from "@bitwarden/common/platform/abstractions/log.service"
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { PaymentComponent } from "./payment.component";
|
||||
import { PaymentComponent } from "./payment/payment.component";
|
||||
|
||||
export interface AdjustStorageDialogData {
|
||||
storageGbPrice: number;
|
||||
|
||||
@@ -4,19 +4,29 @@ import { HeaderModule } from "../../layouts/header/header.module";
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
import { AddCreditDialogComponent } from "./add-credit-dialog.component";
|
||||
import { AdjustPaymentDialogComponent } from "./adjust-payment-dialog.component";
|
||||
import { AdjustPaymentDialogV2Component } from "./adjust-payment-dialog/adjust-payment-dialog-v2.component";
|
||||
import { AdjustPaymentDialogComponent } from "./adjust-payment-dialog/adjust-payment-dialog.component";
|
||||
import { AdjustStorageComponent } from "./adjust-storage.component";
|
||||
import { BillingHistoryComponent } from "./billing-history.component";
|
||||
import { OffboardingSurveyComponent } from "./offboarding-survey.component";
|
||||
import { PaymentV2Component } from "./payment/payment-v2.component";
|
||||
import { PaymentComponent } from "./payment/payment.component";
|
||||
import { PaymentMethodComponent } from "./payment-method.component";
|
||||
import { PaymentComponent } from "./payment.component";
|
||||
import { SecretsManagerSubscribeComponent } from "./sm-subscribe.component";
|
||||
import { TaxInfoComponent } from "./tax-info.component";
|
||||
import { UpdateLicenseDialogComponent } from "./update-license-dialog.component";
|
||||
import { UpdateLicenseComponent } from "./update-license.component";
|
||||
import { VerifyBankAccountComponent } from "./verify-bank-account/verify-bank-account.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [SharedModule, PaymentComponent, TaxInfoComponent, HeaderModule],
|
||||
imports: [
|
||||
SharedModule,
|
||||
PaymentComponent,
|
||||
TaxInfoComponent,
|
||||
HeaderModule,
|
||||
PaymentV2Component,
|
||||
VerifyBankAccountComponent,
|
||||
],
|
||||
declarations: [
|
||||
AddCreditDialogComponent,
|
||||
AdjustPaymentDialogComponent,
|
||||
@@ -27,6 +37,7 @@ import { UpdateLicenseComponent } from "./update-license.component";
|
||||
UpdateLicenseComponent,
|
||||
UpdateLicenseDialogComponent,
|
||||
OffboardingSurveyComponent,
|
||||
AdjustPaymentDialogV2Component,
|
||||
],
|
||||
exports: [
|
||||
SharedModule,
|
||||
@@ -38,6 +49,7 @@ import { UpdateLicenseComponent } from "./update-license.component";
|
||||
UpdateLicenseComponent,
|
||||
UpdateLicenseDialogComponent,
|
||||
OffboardingSurveyComponent,
|
||||
VerifyBankAccountComponent,
|
||||
],
|
||||
})
|
||||
export class BillingSharedModule {}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
export * from "./billing-shared.module";
|
||||
export * from "./payment-method.component";
|
||||
export * from "./payment.component";
|
||||
export * from "./payment/payment.component";
|
||||
export * from "./sm-subscribe.component";
|
||||
export * from "./tax-info.component";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { DIALOG_DATA, DialogConfig, DialogRef } from "@angular/cdk/dialog";
|
||||
import { Component, Inject } from "@angular/core";
|
||||
import { FormBuilder, Validators } from "@angular/forms";
|
||||
|
||||
import { BillingApiServiceAbstraction as BillingApiService } from "@bitwarden/common/billing/abstractions/billilng-api.service.abstraction";
|
||||
import { BillingApiServiceAbstraction as BillingApiService } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@@ -19,7 +19,7 @@ import { AddCreditDialogResult, openAddCreditDialog } from "./add-credit-dialog.
|
||||
import {
|
||||
AdjustPaymentDialogResult,
|
||||
openAdjustPaymentDialog,
|
||||
} from "./adjust-payment-dialog.component";
|
||||
} from "./adjust-payment-dialog/adjust-payment-dialog.component";
|
||||
import { TaxInfoComponent } from "./tax-info.component";
|
||||
|
||||
@Component({
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<div class="tw-mb-4 tw-text-lg">
|
||||
<bit-radio-group formControlName="paymentMethod">
|
||||
<bit-radio-button id="card-payment-method" [value]="PaymentMethodType.Card">
|
||||
<bit-label>
|
||||
<i class="bwi bwi-fw bwi-credit-card" aria-hidden="true"></i>
|
||||
{{ "creditCard" | i18n }}
|
||||
</bit-label>
|
||||
</bit-radio-button>
|
||||
<bit-radio-button
|
||||
id="bank-payment-method"
|
||||
[value]="PaymentMethodType.BankAccount"
|
||||
*ngIf="showBankAccount"
|
||||
>
|
||||
<bit-label>
|
||||
<i class="bwi bwi-fw bwi-bank" aria-hidden="true"></i>
|
||||
{{ "bankAccount" | i18n }}
|
||||
</bit-label>
|
||||
</bit-radio-button>
|
||||
<bit-radio-button
|
||||
id="paypal-payment-method"
|
||||
[value]="PaymentMethodType.PayPal"
|
||||
*ngIf="showPayPal"
|
||||
>
|
||||
<bit-label>
|
||||
<i class="bwi bwi-fw bwi-paypal" aria-hidden="true"></i>
|
||||
{{ "payPal" | i18n }}
|
||||
</bit-label>
|
||||
</bit-radio-button>
|
||||
<bit-radio-button
|
||||
id="credit-payment-method"
|
||||
[value]="PaymentMethodType.Credit"
|
||||
*ngIf="showAccountCredit"
|
||||
>
|
||||
<bit-label>
|
||||
<i class="bwi bwi-fw bwi-dollar" aria-hidden="true"></i>
|
||||
{{ "accountCredit" | i18n }}
|
||||
</bit-label>
|
||||
</bit-radio-button>
|
||||
</bit-radio-group>
|
||||
</div>
|
||||
<!-- Card -->
|
||||
<ng-container *ngIf="usingCard">
|
||||
<div class="tw-grid tw-grid-cols-2 tw-gap-4 tw-mb-4">
|
||||
<div class="tw-col-span-1">
|
||||
<label for="stripe-card-number">
|
||||
{{ "number" | i18n }}
|
||||
<span class="tw-text-xs tw-font-normal">({{ "required" | i18n }})</span>
|
||||
</label>
|
||||
<div id="stripe-card-number" class="form-control stripe-form-control"></div>
|
||||
</div>
|
||||
<div class="tw-col-span-1 tw-flex tw-items-end">
|
||||
<img
|
||||
src="../../../images/cards.png"
|
||||
alt="Visa, MasterCard, Discover, AmEx, JCB, Diners Club, UnionPay"
|
||||
class="tw-max-w-full"
|
||||
/>
|
||||
</div>
|
||||
<div class="tw-col-span-1">
|
||||
<label for="stripe-card-expiry">
|
||||
{{ "expiration" | i18n }}
|
||||
<span class="tw-text-xs tw-font-normal">({{ "required" | i18n }})</span>
|
||||
</label>
|
||||
<div id="stripe-card-expiry" class="form-control stripe-form-control"></div>
|
||||
</div>
|
||||
<div class="tw-col-span-1">
|
||||
<div class="tw-flex">
|
||||
<label for="stripe-card-cvc">
|
||||
{{ "securityCode" | i18n }}
|
||||
<span class="tw-text-xs tw-font-normal">({{ "required" | i18n }})</span>
|
||||
</label>
|
||||
<a
|
||||
href="https://www.cvvnumber.com/cvv.html"
|
||||
tabindex="-1"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
class="ml-auto"
|
||||
appA11yTitle="{{ 'learnMore' | i18n }}"
|
||||
>
|
||||
<i class="bwi bwi-question-circle" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div id="stripe-card-cvc" class="form-control stripe-form-control"></div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<!-- Bank Account -->
|
||||
<ng-container *ngIf="showBankAccount && usingBankAccount">
|
||||
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
|
||||
{{ "verifyBankAccountInitialDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}
|
||||
</app-callout>
|
||||
<div class="tw-grid tw-grid-cols-2 tw-gap-4 tw-mb-4" formGroupName="bankInformation">
|
||||
<bit-form-field class="tw-col-span-1" disableMargin>
|
||||
<bit-label>{{ "routingNumber" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="routingNumber"
|
||||
type="text"
|
||||
formControlName="routingNumber"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field class="tw-col-span-1" disableMargin>
|
||||
<bit-label>{{ "accountNumber" | i18n }}</bit-label>
|
||||
<input
|
||||
bitInput
|
||||
id="accountNumber"
|
||||
type="text"
|
||||
formControlName="accountNumber"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field class="tw-col-span-1" disableMargin>
|
||||
<bit-label>{{ "accountHolderName" | i18n }}</bit-label>
|
||||
<input
|
||||
id="accountHolderName"
|
||||
bitInput
|
||||
type="text"
|
||||
formControlName="accountHolderName"
|
||||
required
|
||||
appInputVerbatim
|
||||
/>
|
||||
</bit-form-field>
|
||||
<bit-form-field class="tw-col-span-1" disableMargin>
|
||||
<bit-label>{{ "bankAccountType" | i18n }}</bit-label>
|
||||
<bit-select id="accountHolderType" formControlName="accountHolderType" required>
|
||||
<bit-option [value]="''" label="-- {{ 'select' | i18n }} --"></bit-option>
|
||||
<bit-option
|
||||
[value]="'company'"
|
||||
label="{{ 'bankAccountTypeCompany' | i18n }}"
|
||||
></bit-option>
|
||||
<bit-option
|
||||
[value]="'individual'"
|
||||
label="{{ 'bankAccountTypeIndividual' | i18n }}"
|
||||
></bit-option>
|
||||
</bit-select>
|
||||
</bit-form-field>
|
||||
</div>
|
||||
</ng-container>
|
||||
<!-- PayPal -->
|
||||
<ng-container *ngIf="showPayPal && usingPayPal">
|
||||
<div class="tw-mb-3">
|
||||
<div id="braintree-container" class="tw-mb-1 tw-content-center"></div>
|
||||
<small class="tw-text-muted">{{ "paypalClickSubmit" | i18n }}</small>
|
||||
</div>
|
||||
</ng-container>
|
||||
<!-- Account Credit -->
|
||||
<ng-container *ngIf="showAccountCredit && usingAccountCredit">
|
||||
<app-callout type="info">
|
||||
{{ "makeSureEnoughCredit" | i18n }}
|
||||
</app-callout>
|
||||
</ng-container>
|
||||
<button *ngIf="!!onSubmit" bitButton bitFormButton buttonType="primary" type="submit">
|
||||
{{ "submit" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
192
apps/web/src/app/billing/shared/payment/payment-v2.component.ts
Normal file
192
apps/web/src/app/billing/shared/payment/payment-v2.component.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from "@angular/core";
|
||||
import { FormControl, FormGroup, Validators } from "@angular/forms";
|
||||
import { Subject } from "rxjs";
|
||||
import { takeUntil } from "rxjs/operators";
|
||||
|
||||
import {
|
||||
BillingApiServiceAbstraction,
|
||||
BraintreeServiceAbstraction,
|
||||
StripeServiceAbstraction,
|
||||
} from "@bitwarden/common/billing/abstractions";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { TokenizedPaymentSourceRequest } from "@bitwarden/common/billing/models/request/tokenized-payment-source.request";
|
||||
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
/**
|
||||
* Render a form that allows the user to enter their payment method, tokenize it against one of our payment providers and,
|
||||
* optionally, submit it using the {@link onSubmit} function if it is provided.
|
||||
*
|
||||
* This component is meant to replace the existing {@link PaymentComponent} which is using the deprecated Stripe Sources API.
|
||||
*/
|
||||
@Component({
|
||||
selector: "app-payment-v2",
|
||||
templateUrl: "./payment-v2.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class PaymentV2Component implements OnInit, OnDestroy {
|
||||
/** Show account credit as a payment option. */
|
||||
@Input() showAccountCredit: boolean = true;
|
||||
/** Show bank account as a payment option. */
|
||||
@Input() showBankAccount: boolean = true;
|
||||
/** Show PayPal as a payment option. */
|
||||
@Input() showPayPal: boolean = true;
|
||||
|
||||
/** The payment method selected by default when the component renders. */
|
||||
@Input() private initialPaymentMethod: PaymentMethodType = PaymentMethodType.Card;
|
||||
/** If provided, will be invoked with the tokenized payment source during form submission. */
|
||||
@Input() protected onSubmit?: (request: TokenizedPaymentSourceRequest) => Promise<void>;
|
||||
|
||||
@Output() submitted = new EventEmitter<PaymentMethodType>();
|
||||
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
protected formGroup = new FormGroup({
|
||||
paymentMethod: new FormControl<PaymentMethodType>(null),
|
||||
bankInformation: new FormGroup({
|
||||
routingNumber: new FormControl<string>("", [Validators.required]),
|
||||
accountNumber: new FormControl<string>("", [Validators.required]),
|
||||
accountHolderName: new FormControl<string>("", [Validators.required]),
|
||||
accountHolderType: new FormControl<string>("", [Validators.required]),
|
||||
}),
|
||||
});
|
||||
|
||||
protected PaymentMethodType = PaymentMethodType;
|
||||
|
||||
constructor(
|
||||
private billingApiService: BillingApiServiceAbstraction,
|
||||
private braintreeService: BraintreeServiceAbstraction,
|
||||
private stripeService: StripeServiceAbstraction,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.formGroup.controls.paymentMethod.patchValue(this.initialPaymentMethod);
|
||||
|
||||
this.stripeService.loadStripe(
|
||||
{
|
||||
cardNumber: "#stripe-card-number",
|
||||
cardExpiry: "#stripe-card-expiry",
|
||||
cardCvc: "#stripe-card-cvc",
|
||||
},
|
||||
this.initialPaymentMethod === PaymentMethodType.Card,
|
||||
);
|
||||
|
||||
if (this.showPayPal) {
|
||||
this.braintreeService.loadBraintree(
|
||||
"#braintree-container",
|
||||
this.initialPaymentMethod === PaymentMethodType.PayPal,
|
||||
);
|
||||
}
|
||||
|
||||
this.formGroup
|
||||
.get("paymentMethod")
|
||||
.valueChanges.pipe(takeUntil(this.destroy$))
|
||||
.subscribe((type) => {
|
||||
this.onPaymentMethodChange(type);
|
||||
});
|
||||
}
|
||||
|
||||
/** Programmatically select the provided payment method. */
|
||||
select = (paymentMethod: PaymentMethodType) => {
|
||||
this.formGroup.value.paymentMethod = paymentMethod;
|
||||
};
|
||||
|
||||
protected submit = async () => {
|
||||
const { type, token } = await this.tokenize();
|
||||
await this.onSubmit({ type, token });
|
||||
this.submitted.emit(type);
|
||||
};
|
||||
|
||||
/**
|
||||
* Tokenize the payment method information entered by the user against one of our payment providers.
|
||||
*
|
||||
* - {@link PaymentMethodType.Card} => [Stripe.confirmCardSetup]{@link https://docs.stripe.com/js/setup_intents/confirm_card_setup}
|
||||
* - {@link PaymentMethodType.BankAccount} => [Stripe.confirmUsBankAccountSetup]{@link https://docs.stripe.com/js/setup_intents/confirm_us_bank_account_setup}
|
||||
* - {@link PaymentMethodType.PayPal} => [Braintree.requestPaymentMethod]{@link https://braintree.github.io/braintree-web-drop-in/docs/current/Dropin.html#requestPaymentMethod}
|
||||
* */
|
||||
async tokenize(): Promise<{ type: PaymentMethodType; token: string }> {
|
||||
const type = this.selected;
|
||||
|
||||
if (this.usingStripe) {
|
||||
const clientSecret = await this.billingApiService.createSetupIntent(type);
|
||||
|
||||
if (this.usingBankAccount) {
|
||||
const token = await this.stripeService.setupBankAccountPaymentMethod(clientSecret, {
|
||||
accountHolderName: this.formGroup.value.bankInformation.accountHolderName,
|
||||
routingNumber: this.formGroup.value.bankInformation.routingNumber,
|
||||
accountNumber: this.formGroup.value.bankInformation.accountNumber,
|
||||
accountHolderType: this.formGroup.value.bankInformation.accountHolderType,
|
||||
});
|
||||
return {
|
||||
type,
|
||||
token,
|
||||
};
|
||||
}
|
||||
|
||||
if (this.usingCard) {
|
||||
const token = await this.stripeService.setupCardPaymentMethod(clientSecret);
|
||||
return {
|
||||
type,
|
||||
token,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (this.usingPayPal) {
|
||||
const token = await this.braintreeService.requestPaymentMethod();
|
||||
return {
|
||||
type,
|
||||
token,
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.destroy$.next();
|
||||
this.destroy$.complete();
|
||||
this.stripeService.unloadStripe();
|
||||
if (this.showPayPal) {
|
||||
this.braintreeService.unloadBraintree();
|
||||
}
|
||||
}
|
||||
|
||||
private onPaymentMethodChange(type: PaymentMethodType): void {
|
||||
switch (type) {
|
||||
case PaymentMethodType.Card: {
|
||||
this.stripeService.mountElements();
|
||||
break;
|
||||
}
|
||||
case PaymentMethodType.PayPal: {
|
||||
this.braintreeService.createDropin();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get selected(): PaymentMethodType {
|
||||
return this.formGroup.value.paymentMethod;
|
||||
}
|
||||
|
||||
protected get usingAccountCredit(): boolean {
|
||||
return this.selected === PaymentMethodType.Credit;
|
||||
}
|
||||
|
||||
protected get usingBankAccount(): boolean {
|
||||
return this.selected === PaymentMethodType.BankAccount;
|
||||
}
|
||||
|
||||
protected get usingCard(): boolean {
|
||||
return this.selected === PaymentMethodType.Card;
|
||||
}
|
||||
|
||||
protected get usingPayPal(): boolean {
|
||||
return this.selected === PaymentMethodType.PayPal;
|
||||
}
|
||||
|
||||
private get usingStripe(): boolean {
|
||||
return this.usingBankAccount || this.usingCard;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { PaymentMethodType } from "@bitwarden/common/billing/enums";
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
@Component({
|
||||
selector: "app-payment",
|
||||
@@ -0,0 +1,18 @@
|
||||
<app-callout type="warning" title="{{ 'verifyBankAccount' | i18n }}">
|
||||
<p>{{ "verifyBankAccountDesc" | i18n }} {{ "verifyBankAccountFailureWarning" | i18n }}</p>
|
||||
<form [formGroup]="formGroup" [bitSubmit]="submit">
|
||||
<bit-form-field class="tw-mr-2 tw-w-40">
|
||||
<bit-label>{{ "amountX" | i18n: "1" }}</bit-label>
|
||||
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount1" />
|
||||
<span bitPrefix>$0.</span>
|
||||
</bit-form-field>
|
||||
<bit-form-field class="tw-mr-2 tw-w-40">
|
||||
<bit-label>{{ "amountX" | i18n: "2" }}</bit-label>
|
||||
<input bitInput type="number" step="1" placeholder="xx" formControlName="amount2" />
|
||||
<span bitPrefix>$0.</span>
|
||||
</bit-form-field>
|
||||
<button *ngIf="onSubmit" type="submit" bitButton bitFormButton buttonType="primary">
|
||||
{{ "submit" | i18n }}
|
||||
</button>
|
||||
</form>
|
||||
</app-callout>
|
||||
@@ -0,0 +1,41 @@
|
||||
import { Component, EventEmitter, Input, Output } from "@angular/core";
|
||||
import { FormBuilder, FormControl, Validators } from "@angular/forms";
|
||||
|
||||
import { VerifyBankAccountRequest } from "@bitwarden/common/billing/models/request/verify-bank-account.request";
|
||||
|
||||
import { SharedModule } from "../../../shared";
|
||||
|
||||
@Component({
|
||||
selector: "app-verify-bank-account",
|
||||
templateUrl: "./verify-bank-account.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class VerifyBankAccountComponent {
|
||||
@Input() onSubmit?: (request: VerifyBankAccountRequest) => Promise<void>;
|
||||
@Output() submitted = new EventEmitter();
|
||||
|
||||
protected formGroup = this.formBuilder.group({
|
||||
amount1: new FormControl<number>(null, [
|
||||
Validators.required,
|
||||
Validators.min(0),
|
||||
Validators.max(99),
|
||||
]),
|
||||
amount2: new FormControl<number>(null, [
|
||||
Validators.required,
|
||||
Validators.min(0),
|
||||
Validators.max(99),
|
||||
]),
|
||||
});
|
||||
|
||||
constructor(private formBuilder: FormBuilder) {}
|
||||
|
||||
submit = async () => {
|
||||
const request = new VerifyBankAccountRequest(
|
||||
this.formGroup.value.amount1,
|
||||
this.formGroup.value.amount2,
|
||||
);
|
||||
await this.onSubmit(request);
|
||||
this.submitted.emit();
|
||||
};
|
||||
}
|
||||
@@ -40,6 +40,7 @@ import { I18nService as I18nServiceAbstraction } from "@bitwarden/common/platfor
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService as PlatformUtilsServiceAbstraction } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { AbstractStorageService } from "@bitwarden/common/platform/abstractions/storage.service";
|
||||
import { BiometricsService } from "@bitwarden/common/platform/biometrics/biometric.service";
|
||||
import { ThemeType } from "@bitwarden/common/platform/enums";
|
||||
import { MemoryStorageService } from "@bitwarden/common/platform/services/memory-storage.service";
|
||||
// eslint-disable-next-line import/no-restricted-paths -- Implementation for memory storage
|
||||
@@ -62,6 +63,7 @@ import { WebSetPasswordJitService, WebRegistrationFinishService, WebLoginService
|
||||
import { AcceptOrganizationInviteService } from "../auth/organization-invite/accept-organization.service";
|
||||
import { HtmlStorageService } from "../core/html-storage.service";
|
||||
import { I18nService } from "../core/i18n.service";
|
||||
import { WebBiometricsService } from "../platform/web-biometric.service";
|
||||
import { WebEnvironmentService } from "../platform/web-environment.service";
|
||||
import { WebMigrationRunner } from "../platform/web-migration-runner";
|
||||
import { WebStorageServiceProvider } from "../platform/web-storage-service.provider";
|
||||
@@ -164,6 +166,11 @@ const safeProviders: SafeProvider[] = [
|
||||
useClass: WebEnvironmentService,
|
||||
deps: [WINDOW, StateProvider, AccountService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: BiometricsService,
|
||||
useClass: WebBiometricsService,
|
||||
deps: [],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: ThemeStateService,
|
||||
useFactory: (globalStateProvider: GlobalStateProvider) =>
|
||||
|
||||
@@ -186,20 +186,6 @@ export class WebPlatformUtilsService implements PlatformUtilsService {
|
||||
throw new Error("Cannot read from clipboard on web.");
|
||||
}
|
||||
|
||||
supportsBiometric() {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
authenticateBiometric() {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
biometricsNeedsSetup: () => Promise<boolean>;
|
||||
biometricsSupportsAutoSetup(): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
biometricsSetup: () => Promise<void>;
|
||||
|
||||
supportsSecureStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ import { PreferencesComponent } from "./settings/preferences.component";
|
||||
import { GeneratorComponent } from "./tools/generator.component";
|
||||
import { ReportsModule } from "./tools/reports";
|
||||
import { AccessComponent } from "./tools/send/access.component";
|
||||
import { SendAccessExplainerComponent } from "./tools/send/send-access-explainer.component";
|
||||
import { SendComponent } from "./tools/send/send.component";
|
||||
import { VaultModule } from "./vault/individual-vault/vault.module";
|
||||
|
||||
@@ -146,11 +147,6 @@ const routes: Routes = [
|
||||
canActivate: [unauthGuardFn()],
|
||||
data: { titleId: "deleteAccount" } satisfies DataProperties,
|
||||
},
|
||||
{
|
||||
path: "send/:sendId/:key",
|
||||
component: AccessComponent,
|
||||
data: { titleId: "Bitwarden Send" } satisfies DataProperties,
|
||||
},
|
||||
{
|
||||
path: "update-temp-password",
|
||||
component: UpdateTempPasswordComponent,
|
||||
@@ -211,6 +207,24 @@ const routes: Routes = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "send/:sendId/:key",
|
||||
data: {
|
||||
pageTitle: "viewSend",
|
||||
showReadonlyHostname: true,
|
||||
} satisfies DataProperties & AnonLayoutWrapperData,
|
||||
children: [
|
||||
{
|
||||
path: "",
|
||||
component: AccessComponent,
|
||||
},
|
||||
{
|
||||
path: "",
|
||||
outlet: "secondary",
|
||||
component: SendAccessExplainerComponent,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: "set-password-jit",
|
||||
canActivate: [canAccessFeature(FeatureFlag.EmailVerification)],
|
||||
|
||||
27
apps/web/src/app/platform/web-biometric.service.ts
Normal file
27
apps/web/src/app/platform/web-biometric.service.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { BiometricsService } from "@bitwarden/common/platform/biometrics/biometric.service";
|
||||
|
||||
export class WebBiometricsService extends BiometricsService {
|
||||
async supportsBiometric(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async isBiometricUnlockAvailable(): Promise<boolean> {
|
||||
return false;
|
||||
}
|
||||
|
||||
async authenticateBiometric(): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async biometricsNeedsSetup(): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async biometricsSupportsAutoSetup(): Promise<boolean> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
|
||||
async biometricsSetup(): Promise<void> {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,10 @@ export class PreferencesComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
return;
|
||||
}
|
||||
const values = this.form.value;
|
||||
|
||||
// must get raw value b/c the vault timeout action is disabled when a policy is applied
|
||||
// which removes the timeout action property and value from the normal form.value.
|
||||
const values = this.form.getRawValue();
|
||||
|
||||
const activeAcct = await firstValueFrom(this.accountService.activeAccount$);
|
||||
|
||||
|
||||
@@ -1,85 +1,52 @@
|
||||
<form [formGroup]="formGroup" [bitSubmit]="load">
|
||||
<div
|
||||
class="tw-mx-auto tw-mt-5 tw-flex tw-max-w-xl tw-flex-col tw-items-center tw-justify-center tw-p-8"
|
||||
>
|
||||
<img class="logo logo-themed" alt="Bitwarden" />
|
||||
<div class="tw-mt-5 tw-w-full">
|
||||
<h2 bitTypography="h2" class="tw-mb-4 tw-text-center">View Send</h2>
|
||||
</div>
|
||||
<div class="tw-w-full tw-text-center" *ngIf="creatorIdentifier != null">
|
||||
<p>{{ "sendAccessCreatorIdentifier" | i18n: creatorIdentifier }}</p>
|
||||
</div>
|
||||
<bit-callout *ngIf="hideEmail" type="warning" title="{{ 'warning' | i18n }}">
|
||||
{{ "viewSendHiddenEmailWarning" | i18n }}
|
||||
<a bitLink href="https://bitwarden.com/help/receive-send/" target="_blank" rel="noreferrer">{{
|
||||
"learnMore" | i18n
|
||||
}}</a
|
||||
>.
|
||||
</bit-callout>
|
||||
<div
|
||||
class="tw-mt-3 tw-w-10/12 tw-rounded-md tw-border tw-border-solid tw-border-secondary-300 tw-bg-background tw-p-6"
|
||||
>
|
||||
<ng-container *ngIf="!loading; else spinner">
|
||||
<app-send-access-password
|
||||
(setPasswordEvent)="setPassword($event)"
|
||||
*ngIf="passwordRequired && !error"
|
||||
></app-send-access-password>
|
||||
<bit-no-items [icon]="expiredSendIcon" class="tw-text-main" *ngIf="unavailable">
|
||||
<ng-container slot="description">{{ "sendAccessUnavailable" | i18n }}</ng-container>
|
||||
</bit-no-items>
|
||||
<bit-no-items [icon]="expiredSendIcon" class="tw-text-main" *ngIf="error">
|
||||
<ng-container slot="description">{{ "unexpectedErrorSend" | i18n }}</ng-container>
|
||||
</bit-no-items>
|
||||
<div *ngIf="!passwordRequired && send && !error && !unavailable">
|
||||
<p class="tw-text-center">
|
||||
<b>{{ send.name }}</b>
|
||||
</p>
|
||||
<hr />
|
||||
<!-- Text -->
|
||||
<ng-container *ngIf="send.type === sendType.Text">
|
||||
<app-send-access-text [send]="send"></app-send-access-text>
|
||||
</ng-container>
|
||||
<!-- File -->
|
||||
<ng-container *ngIf="send.type === sendType.File">
|
||||
<app-send-access-file
|
||||
[send]="send"
|
||||
[decKey]="decKey"
|
||||
[accessRequest]="accessRequest"
|
||||
></app-send-access-file>
|
||||
</ng-container>
|
||||
<p *ngIf="expirationDate" class="tw-text-center tw-text-muted">
|
||||
Expires: {{ expirationDate | date: "medium" }}
|
||||
</p>
|
||||
</div>
|
||||
<bit-callout *ngIf="hideEmail" type="warning" title="{{ 'warning' | i18n }}">
|
||||
{{ "viewSendHiddenEmailWarning" | i18n }}
|
||||
<a bitLink href="https://bitwarden.com/help/receive-send/" target="_blank" rel="noreferrer">{{
|
||||
"learnMore" | i18n
|
||||
}}</a
|
||||
>.
|
||||
</bit-callout>
|
||||
<ng-container *ngIf="!loading; else spinner">
|
||||
<app-send-access-password
|
||||
(setPasswordEvent)="setPassword($event)"
|
||||
*ngIf="passwordRequired && !error"
|
||||
></app-send-access-password>
|
||||
<bit-no-items [icon]="expiredSendIcon" class="tw-text-main" *ngIf="unavailable">
|
||||
<ng-container slot="description">{{ "sendAccessUnavailable" | i18n }}</ng-container>
|
||||
</bit-no-items>
|
||||
<bit-no-items [icon]="expiredSendIcon" class="tw-text-main" *ngIf="error">
|
||||
<ng-container slot="description">{{ "unexpectedErrorSend" | i18n }}</ng-container>
|
||||
</bit-no-items>
|
||||
<div *ngIf="!passwordRequired && send && !error && !unavailable">
|
||||
<p class="tw-text-center">
|
||||
<b>{{ send.name }}</b>
|
||||
</p>
|
||||
<hr />
|
||||
<!-- Text -->
|
||||
<ng-container *ngIf="send.type === sendType.Text">
|
||||
<app-send-access-text [send]="send"></app-send-access-text>
|
||||
</ng-container>
|
||||
<ng-template #spinner>
|
||||
<div class="tw-text-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-2x tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div class="tw-mt-5 tw-w-10/12 tw-text-center tw-text-muted">
|
||||
<p bitTypography="body2" class="tw-mb-0">
|
||||
{{ "sendAccessTaglineProductDesc" | i18n }}
|
||||
{{ "sendAccessTaglineLearnMore" | i18n }}
|
||||
<a
|
||||
bitLink
|
||||
href="https://www.bitwarden.com/products/send?source=web-vault"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>Bitwarden Send</a
|
||||
>
|
||||
{{ "sendAccessTaglineOr" | i18n }}
|
||||
<a bitLink [routerLink]="registerRoute$ | async" target="_blank" rel="noreferrer">{{
|
||||
"sendAccessTaglineSignUp" | i18n
|
||||
}}</a>
|
||||
{{ "sendAccessTaglineTryToday" | i18n }}
|
||||
<!-- File -->
|
||||
<ng-container *ngIf="send.type === sendType.File">
|
||||
<app-send-access-file
|
||||
[send]="send"
|
||||
[decKey]="decKey"
|
||||
[accessRequest]="accessRequest"
|
||||
></app-send-access-file>
|
||||
</ng-container>
|
||||
<p *ngIf="expirationDate" class="tw-text-center tw-text-muted">
|
||||
Expires: {{ expirationDate | date: "medium" }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ng-template #spinner>
|
||||
<div class="tw-text-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-2x tw-text-muted"
|
||||
title="{{ 'loading' | i18n }}"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
<span class="tw-sr-only">{{ "loading" | i18n }}</span>
|
||||
</div>
|
||||
</ng-template>
|
||||
</form>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, OnInit } from "@angular/core";
|
||||
import { FormBuilder } from "@angular/forms";
|
||||
import { ActivatedRoute } from "@angular/router";
|
||||
|
||||
import { AnonLayoutWrapperDataService } from "@bitwarden/auth/angular";
|
||||
import { RegisterRouteService } from "@bitwarden/auth/common";
|
||||
import { ErrorResponse } from "@bitwarden/common/models/response/error.response";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
@@ -70,6 +71,7 @@ export class AccessComponent implements OnInit {
|
||||
private i18nService: I18nService,
|
||||
private configService: ConfigService,
|
||||
private registerRouteService: RegisterRouteService,
|
||||
private layoutWrapperDataService: AnonLayoutWrapperDataService,
|
||||
protected formBuilder: FormBuilder,
|
||||
) {}
|
||||
|
||||
@@ -151,6 +153,15 @@ export class AccessComponent implements OnInit {
|
||||
!this.passwordRequired &&
|
||||
!this.loading &&
|
||||
!this.unavailable;
|
||||
|
||||
if (this.creatorIdentifier != null) {
|
||||
this.layoutWrapperDataService.setAnonLayoutWrapperData({
|
||||
pageSubtitle: {
|
||||
subtitle: this.i18nService.t("sendAccessCreatorIdentifier", this.creatorIdentifier),
|
||||
translate: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
protected setPassword(password: string) {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<div class="tw-text-center tw-text-muted">
|
||||
<p bitTypography="body2" class="tw-mb-0">
|
||||
{{ "sendAccessTaglineProductDesc" | i18n }}
|
||||
{{ "sendAccessTaglineLearnMore" | i18n }}
|
||||
<a
|
||||
bitLink
|
||||
href="https://www.bitwarden.com/products/send?source=web-vault"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>Bitwarden Send</a
|
||||
>
|
||||
{{ "sendAccessTaglineOr" | i18n }}
|
||||
<a bitLink [routerLink]="registerRoute$ | async" target="_blank" rel="noreferrer">{{
|
||||
"sendAccessTaglineSignUp" | i18n
|
||||
}}</a>
|
||||
{{ "sendAccessTaglineTryToday" | i18n }}
|
||||
</p>
|
||||
</div>
|
||||
@@ -0,0 +1,17 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { RegisterRouteService } from "@bitwarden/auth/common";
|
||||
|
||||
import { SharedModule } from "../../shared";
|
||||
|
||||
@Component({
|
||||
selector: "app-send-access-explainer",
|
||||
templateUrl: "send-access-explainer.component.html",
|
||||
standalone: true,
|
||||
imports: [SharedModule],
|
||||
})
|
||||
export class SendAccessExplainerComponent {
|
||||
// TODO: remove when email verification flag is removed
|
||||
registerRoute$ = this.registerRouteService.registerRoute$();
|
||||
constructor(private registerRouteService: RegisterRouteService) {}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/pl
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
@Component({
|
||||
selector: "app-vault-collections",
|
||||
@@ -29,6 +29,7 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
|
||||
accountService: AccountService,
|
||||
protected dialogRef: DialogRef,
|
||||
@Inject(DIALOG_DATA) params: CollectionsDialogParams,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
collectionService,
|
||||
@@ -39,6 +40,7 @@ export class CollectionsComponent extends BaseCollectionsComponent implements On
|
||||
logService,
|
||||
configService,
|
||||
accountService,
|
||||
toastService,
|
||||
);
|
||||
this.cipherId = params?.cipherId;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||
import { SyncService } from "@bitwarden/common/platform/sync";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import { OrganizationUserResetPasswordService } from "../../../../admin-console/organizations/members/services/organization-user-reset-password/organization-user-reset-password.service";
|
||||
import { EnrollMasterPasswordReset } from "../../../../admin-console/organizations/users/enroll-master-password-reset.component";
|
||||
@@ -50,6 +50,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
|
||||
private dialogService: DialogService,
|
||||
private resetPasswordService: OrganizationUserResetPasswordService,
|
||||
private userVerificationService: UserVerificationService,
|
||||
private toastService: ToastService,
|
||||
) {}
|
||||
|
||||
async ngOnInit() {
|
||||
@@ -158,6 +159,7 @@ export class OrganizationOptionsComponent implements OnInit, OnDestroy {
|
||||
this.syncService,
|
||||
this.logService,
|
||||
this.userVerificationService,
|
||||
this.toastService,
|
||||
);
|
||||
} else {
|
||||
// Remove reset password
|
||||
|
||||
@@ -718,12 +718,12 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
const result: ViewCipherDialogCloseResult = await lastValueFrom(dialogRef.closed);
|
||||
|
||||
// If the dialog was closed by deleting the cipher, refresh the vault.
|
||||
if (result.action === ViewCipherDialogResult.deleted) {
|
||||
if (result?.action === ViewCipherDialogResult.deleted) {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
// If the dialog was closed by any other action (close button, escape key, etc), navigate back to the vault.
|
||||
if (!result.action) {
|
||||
if (!result?.action) {
|
||||
this.go({ cipherId: null, itemId: null, action: null });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { CipherData } from "@bitwarden/common/vault/models/data/cipher.data";
|
||||
import { Cipher } from "@bitwarden/common/vault/models/domain/cipher";
|
||||
import { CipherCollectionsRequest } from "@bitwarden/common/vault/models/request/cipher-collections.request";
|
||||
import { CollectionView } from "@bitwarden/common/vault/models/view/collection.view";
|
||||
import { DialogService } from "@bitwarden/components";
|
||||
import { DialogService, ToastService } from "@bitwarden/components";
|
||||
|
||||
import {
|
||||
CollectionsComponent as BaseCollectionsComponent,
|
||||
@@ -41,6 +41,7 @@ export class CollectionsComponent extends BaseCollectionsComponent {
|
||||
accountService: AccountService,
|
||||
protected dialogRef: DialogRef,
|
||||
@Inject(DIALOG_DATA) params: OrgVaultCollectionsDialogParams,
|
||||
toastService: ToastService,
|
||||
) {
|
||||
super(
|
||||
collectionService,
|
||||
@@ -53,6 +54,7 @@ export class CollectionsComponent extends BaseCollectionsComponent {
|
||||
accountService,
|
||||
dialogRef,
|
||||
params,
|
||||
toastService,
|
||||
);
|
||||
this.allowSelectNone = true;
|
||||
this.collectionIds = params?.collectionIds;
|
||||
|
||||
@@ -113,10 +113,32 @@
|
||||
{{ "new" | i18n }}<i class="bwi bwi-angle-down tw-ml-2" aria-hidden="true"></i>
|
||||
</button>
|
||||
<bit-menu #addOptions aria-labelledby="newItemDropdown">
|
||||
<button type="button" bitMenuItem (click)="addCipher()">
|
||||
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i>
|
||||
{{ "item" | i18n }}
|
||||
</button>
|
||||
<ng-container [ngSwitch]="extensionRefreshEnabled">
|
||||
<ng-container *ngSwitchCase="true">
|
||||
<button type="button" bitMenuItem (click)="addCipher(CipherType.Login)">
|
||||
<i class="bwi bwi-globe" slot="start" aria-hidden="true"></i>
|
||||
{{ "typeLogin" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitMenuItem (click)="addCipher(CipherType.Card)">
|
||||
<i class="bwi bwi-credit-card" slot="start" aria-hidden="true"></i>
|
||||
{{ "typeCard" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitMenuItem (click)="addCipher(CipherType.Identity)">
|
||||
<i class="bwi bwi-id-card" slot="start" aria-hidden="true"></i>
|
||||
{{ "typeIdentity" | i18n }}
|
||||
</button>
|
||||
<button type="button" bitMenuItem (click)="addCipher(CipherType.SecureNote)">
|
||||
<i class="bwi bwi-sticky-note" slot="start" aria-hidden="true"></i>
|
||||
{{ "note" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
<ng-container *ngSwitchCase="false">
|
||||
<button type="button" bitMenuItem (click)="addCipher()">
|
||||
<i class="bwi bwi-fw bwi-globe" aria-hidden="true"></i>
|
||||
{{ "item" | i18n }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<button type="button" bitMenuItem (click)="addCollection()">
|
||||
<i class="bwi bwi-fw bwi-collection" aria-hidden="true"></i>
|
||||
{{ "collection" | i18n }}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { ProductTierType } from "@bitwarden/common/billing/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import {
|
||||
DialogService,
|
||||
@@ -67,7 +68,7 @@ export class VaultHeaderComponent implements OnInit {
|
||||
@Input() searchText: string;
|
||||
|
||||
/** Emits an event when the new item button is clicked in the header */
|
||||
@Output() onAddCipher = new EventEmitter<void>();
|
||||
@Output() onAddCipher = new EventEmitter<CipherType | undefined>();
|
||||
|
||||
/** Emits an event when the new collection button is clicked in the header */
|
||||
@Output() onAddCollection = new EventEmitter<void>();
|
||||
@@ -89,6 +90,14 @@ export class VaultHeaderComponent implements OnInit {
|
||||
|
||||
protected restrictProviderAccessFlag = false;
|
||||
|
||||
/**
|
||||
* Whether the extension refresh feature flag is enabled.
|
||||
*/
|
||||
protected extensionRefreshEnabled = false;
|
||||
|
||||
/** The cipher type enum. */
|
||||
protected CipherType = CipherType;
|
||||
|
||||
constructor(
|
||||
private organizationService: OrganizationService,
|
||||
private i18nService: I18nService,
|
||||
@@ -102,6 +111,9 @@ export class VaultHeaderComponent implements OnInit {
|
||||
this.restrictProviderAccessFlag = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.RestrictProviderAccess,
|
||||
);
|
||||
this.extensionRefreshEnabled = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.ExtensionRefresh,
|
||||
);
|
||||
}
|
||||
|
||||
get title() {
|
||||
@@ -194,8 +206,8 @@ export class VaultHeaderComponent implements OnInit {
|
||||
return this.collection.node.canEdit(this.organization);
|
||||
}
|
||||
|
||||
addCipher() {
|
||||
this.onAddCipher.emit();
|
||||
addCipher(cipherType?: CipherType) {
|
||||
this.onAddCipher.emit(cipherType);
|
||||
}
|
||||
|
||||
async addCollection() {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[organization]="organization"
|
||||
[collection]="selectedCollection"
|
||||
[searchText]="currentSearchText$ | async"
|
||||
(onAddCipher)="addCipher()"
|
||||
(onAddCipher)="addCipher($event)"
|
||||
(onAddCollection)="addCollection()"
|
||||
(onEditCollection)="editCollection(selectedCollection.node, $event.tab, $event.readonly)"
|
||||
(onDeleteCollection)="deleteCollection(selectedCollection.node)"
|
||||
|
||||
@@ -54,6 +54,7 @@ import { OrganizationId } from "@bitwarden/common/types/guid";
|
||||
import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service";
|
||||
import { CollectionService } from "@bitwarden/common/vault/abstractions/collection.service";
|
||||
import { TotpService } from "@bitwarden/common/vault/abstractions/totp.service";
|
||||
import { CipherType } from "@bitwarden/common/vault/enums";
|
||||
import { CipherRepromptType } from "@bitwarden/common/vault/enums/cipher-reprompt-type";
|
||||
import { TreeNode } from "@bitwarden/common/vault/models/domain/tree-node";
|
||||
import { CipherView } from "@bitwarden/common/vault/models/view/cipher.view";
|
||||
@@ -786,14 +787,14 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
async addCipher() {
|
||||
async addCipher(cipherType?: CipherType) {
|
||||
let collections: CollectionView[] = [];
|
||||
|
||||
// Admins limited to only adding items to collections they have access to.
|
||||
collections = await firstValueFrom(this.editableCollections$);
|
||||
|
||||
await this.editCipher(null, (comp) => {
|
||||
comp.type = this.activeFilter.cipherType;
|
||||
comp.type = cipherType || this.activeFilter.cipherType;
|
||||
comp.collections = collections;
|
||||
if (this.activeFilter.collectionId) {
|
||||
comp.collectionIds = [this.activeFilter.collectionId];
|
||||
|
||||
6
apps/web/src/images/logo-white.svg
Normal file
6
apps/web/src/images/logo-white.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg viewBox="0 0 290 45" fill="#FFF" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M69.799 10.713c3.325 0 5.911 1.248 7.811 3.848 1.9 2.549 2.85 6.033 2.85 10.453 0 4.576-.95 8.113-2.902 10.61-1.953 2.547-4.592 3.743-7.918 3.743-3.325 0-5.858-1.144-7.758-3.536h-.528l-1.003 2.444a.976.976 0 0 1-.897.572H55.23a.94.94 0 0 1-.95-.936V1.352a.94.94 0 0 1 .95-.936h5.7a.94.94 0 0 1 .95.936v8.009c0 1.144-.105 2.964-.316 5.46h.317c1.741-2.704 4.433-4.108 7.917-4.108Zm-2.428 6.084c-1.847 0-3.273.572-4.17 1.717-.844 1.144-1.32 3.068-1.32 5.668v.832c0 2.964.423 5.097 1.32 6.345.897 1.248 2.322 1.924 4.275 1.924 1.531 0 2.85-.728 3.748-2.184.897-1.404 1.372-3.537 1.372-6.189 0-2.704-.475-4.732-1.372-6.084-.95-1.352-2.27-2.029-3.853-2.029ZM93.022 38.9h-5.7a.94.94 0 0 1-.95-.936V12.221a.94.94 0 0 1 .95-.936h5.7a.94.94 0 0 1 .95.936v25.69c.053.468-.422.988-.95.988Zm20.849-5.564c1.108 0 2.428-.208 4.011-.624a.632.632 0 0 1 .792.624v4.316a.64.64 0 0 1-.37.572c-1.794.728-4.064 1.092-6.597 1.092-3.062 0-5.278-.728-6.651-2.288-1.372-1.508-2.111-3.796-2.111-6.812V16.953h-3.008c-.37 0-.634-.26-.634-.624v-2.444c0-.052.053-.104.053-.156l4.17-2.444 2.058-5.408c.106-.26.317-.417.581-.417h3.8c.369 0 .633.26.633.625v5.252h7.548c.158 0 .317.156.317.312v4.68c0 .364-.264.624-.634.624h-7.178v13.21c0 1.04.317 1.872.897 2.34.528.572 1.373.832 2.323.832Zm35.521 5.564c-.739 0-1.319-.468-1.636-1.144l-5.595-16.797c-.369-1.196-.844-3.016-1.478-5.357h-.158l-.528 1.873-1.108 3.536-5.753 16.797c-.211.676-.845 1.092-1.584 1.092a1.628 1.628 0 0 1-1.583-1.196l-7.02-24.182c-.211-.728.369-1.508 1.214-1.508h.158c.528 0 1.003.364 1.161.884l4.117 14.717c1.003 3.849 1.689 6.657 2.006 8.53h.158c.95-3.85 1.689-6.397 2.164-7.698l5.331-15.393c.211-.624.792-1.04 1.531-1.04.686 0 1.267.416 1.478 1.04l4.961 15.29c1.214 3.9 1.953 6.396 2.217 7.696h.158c.159-1.04.792-3.952 2.006-8.633l3.958-14.509c.159-.52.634-.884 1.162-.884.791 0 1.372.728 1.161 1.508l-6.651 24.182c-.211.728-.844 1.196-1.636 1.196h-.211Zm31.352 0a.962.962 0 0 1-.95-.832l-.475-3.432h-.264c-1.372 1.716-2.745 2.964-4.223 3.692-1.425.728-3.166 1.04-5.119 1.04-2.692 0-4.751-.676-6.228-2.028-1.32-1.196-2.059-2.808-2.164-4.836-.212-2.704.95-5.305 3.166-6.813 2.27-1.456 5.437-2.34 9.712-2.34l5.173-.156v-1.768c0-2.6-.528-4.473-1.637-5.773-1.108-1.3-2.744-1.924-5.067-1.924-2.216 0-4.433.52-6.756 1.612-.58.26-1.266 0-1.53-.572s0-1.248.58-1.456c2.639-1.04 5.226-1.612 7.865-1.612 3.008 0 5.225.78 6.756 2.34 1.478 1.508 2.216 3.953 2.216 7.125v16.901c-.052.312-.527.832-1.055.832Zm-10.926-1.768c2.956 0 5.226-.832 6.862-2.444 1.689-1.612 2.533-3.952 2.533-6.813v-2.6l-4.75.208c-3.853.156-6.545.78-8.234 1.768-1.636.988-2.481 2.6-2.481 4.68 0 1.665.528 3.017 1.531 3.953 1.161.78 2.639 1.248 4.539 1.248Zm31.246-25.638c.792 0 1.584.052 2.481.156a1.176 1.176 0 0 1 1.003 1.352c-.106.624-.739.988-1.372.884-.792-.104-1.584-.208-2.375-.208-2.323 0-4.223.988-5.701 2.912-1.478 1.925-2.217 4.42-2.217 7.333v13.625c0 .676-.527 1.196-1.214 1.196-.686 0-1.213-.52-1.213-1.196V13.105c0-.572.475-1.04 1.055-1.04.581 0 1.056.416 1.056.988l.211 3.848h.158c1.109-1.976 2.323-3.38 3.589-4.16 1.214-.832 2.745-1.248 4.539-1.248Zm18.579 0c1.953 0 3.695.364 5.12 1.04 1.478.676 2.745 1.924 3.853 3.64h.158a122.343 122.343 0 0 1-.158-6.084V1.612c0-.676.528-1.196 1.214-1.196.686 0 1.214.52 1.214 1.196v36.351c0 .468-.37.832-.845.832a.852.852 0 0 1-.844-.78l-.528-3.38h-.211c-2.058 3.068-5.067 4.576-8.92 4.576-3.8 0-6.598-1.144-8.656-3.484-1.953-2.34-3.008-5.668-3.008-10.089 0-4.628.95-8.165 2.955-10.66 2.006-2.237 4.856-3.485 8.656-3.485Zm0 2.236c-3.008 0-5.225 1.04-6.756 3.12-1.478 2.029-2.216 4.993-2.216 8.945 0 7.593 3.008 11.39 9.025 11.39 3.114 0 5.331-.885 6.756-2.653 1.478-1.768 2.164-4.68 2.164-8.737v-.416c0-4.16-.686-7.124-2.164-8.893-1.372-1.872-3.642-2.756-6.809-2.756Zm31.616 25.638c-3.959 0-7.02-1.196-9.289-3.64-2.217-2.392-3.326-5.772-3.326-10.089 0-4.316 1.056-7.748 3.22-10.297 2.164-2.6 5.014-3.9 8.656-3.9 3.167 0 5.753 1.092 7.548 3.276 1.9 2.184 2.797 5.2 2.797 8.997v1.976h-19.634c.052 3.692.897 6.5 2.639 8.477 1.741 1.976 4.169 2.86 7.389 2.86 1.531 0 2.956-.104 4.117-.312.844-.156 1.847-.416 3.061-.832.686-.26 1.425.26 1.425.988 0 .416-.264.832-.686.988-1.267.52-2.481.832-3.589 1.04-1.32.364-2.745.468-4.328.468Zm-.739-25.69c-2.639 0-4.75.832-6.334 2.548-1.583 1.665-2.48 4.16-2.797 7.333h16.89c0-3.068-.686-5.564-2.059-7.28-1.372-1.717-3.272-2.6-5.7-2.6ZM288.733 38.9c-.686 0-1.214-.52-1.214-1.196V21.426c0-2.704-.58-4.68-1.689-5.877-1.214-1.196-2.955-1.872-5.383-1.872-3.273 0-5.648.78-7.126 2.444-1.478 1.613-2.322 4.265-2.322 7.853V37.6c0 .676-.528 1.196-1.214 1.196-.686 0-1.214-.52-1.214-1.196V13.105c0-.624.475-1.092 1.108-1.092.581 0 1.003.416 1.109.936l.316 2.704h.159c1.794-2.808 4.908-4.212 9.448-4.212 6.175 0 9.289 3.276 9.289 9.829V37.6c-.053.727-.633 1.3-1.267 1.3ZM90.225 0c-2.48 0-4.486 1.872-4.486 4.212v.416c0 2.289 2.058 4.213 4.486 4.213s4.486-1.924 4.486-4.213v-.364C94.711 1.872 92.653 0 90.225 0Z" />
|
||||
<path
|
||||
d="M32.041 24.546V5.95H18.848v33.035c2.336-1.22 4.427-2.547 6.272-3.98 4.614-3.565 6.921-7.051 6.921-10.46Zm5.654-22.314v22.314c0 1.665-.329 3.317-.986 4.953-.658 1.637-1.473 3.09-2.445 4.359-.971 1.268-2.13 2.503-3.475 3.704-1.345 1.2-2.586 2.199-3.725 2.993a46.963 46.963 0 0 1-3.563 2.251c-1.237.707-2.116 1.187-2.636 1.439-.52.251-.938.445-1.252.58-.235.117-.49.175-.765.175s-.53-.058-.766-.174c-.314-.136-.731-.33-1.252-.581-.52-.252-1.398-.732-2.635-1.439a47.003 47.003 0 0 1-3.564-2.251c-1.138-.794-2.38-1.792-3.725-2.993-1.345-1.2-2.503-2.436-3.475-3.704-.972-1.27-1.787-2.722-2.444-4.359C.329 27.863 0 26.211 0 24.546V2.232c0-.504.187-.94.56-1.308A1.823 1.823 0 0 1 1.885.372H35.81c.511 0 .953.184 1.326.552.373.368.56.804.56 1.308Z" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.7 KiB |
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=1010" />
|
||||
<meta name="theme-color" content="#175DDC" />
|
||||
|
||||
<title page-title>Bitwarden Web Vault</title>
|
||||
<title page-title>Bitwarden Web vault</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="images/icons/apple-touch-icon.png" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="images/icons/favicon-32x32.png" />
|
||||
@@ -15,16 +15,14 @@
|
||||
</head>
|
||||
<body class="layout_frontend">
|
||||
<app-root>
|
||||
<div class="mt-5 d-flex justify-content-center">
|
||||
<div>
|
||||
<img class="mb-4 logo logo-themed" alt="Bitwarden" />
|
||||
<p class="text-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-2x text-muted"
|
||||
title="Loading"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</p>
|
||||
<div class="tw-p-8 tw-flex">
|
||||
<img class="new-logo-themed" alt="Bitwarden" />
|
||||
<div class="spinner-container tw-justify-center">
|
||||
<i
|
||||
class="bwi bwi-spinner bwi-spin bwi-3x tw-text-muted"
|
||||
title="Loading"
|
||||
aria-hidden="true"
|
||||
></i>
|
||||
</div>
|
||||
</div>
|
||||
</app-root>
|
||||
|
||||
@@ -964,6 +964,12 @@
|
||||
"newAccountCreated": {
|
||||
"message": "U nuwe rekening is geskep! U kan nou aanteken."
|
||||
},
|
||||
"newAccountCreated2": {
|
||||
"message": "Your new account has been created!"
|
||||
},
|
||||
"youHaveBeenLoggedIn": {
|
||||
"message": "You have been logged in!"
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "Rekening suksesvol geskep."
|
||||
},
|
||||
@@ -4983,6 +4989,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewSend": {
|
||||
"message": "View Send",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"viewSendHiddenEmailWarning": {
|
||||
"message": "Die Bitwarden-gebruiker wat hierdie Send geskep het, het gekies om hul e-posadres te verberg. U moet verseker dat u die bron van hierdie skakel vertrou voordat u die inhoud gebruik of aflaai.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
@@ -9008,5 +9018,12 @@
|
||||
},
|
||||
"secretsManagerWithFreePasswordManagerInfo": {
|
||||
"message": "Your complementary one year Password Manager subscription will upgrade to the selected plan. You will not be charged until the complimentary period is over."
|
||||
},
|
||||
"publicApi": {
|
||||
"message": "Public API",
|
||||
"description": "The text, 'API', is an acronymn and should not be translated."
|
||||
},
|
||||
"additionalContentAvailable": {
|
||||
"message": "Additional content is available"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,6 +964,12 @@
|
||||
"newAccountCreated": {
|
||||
"message": "تم إنشاء حساب جديد لك! بإمكانك الآن تسجيل الدخول."
|
||||
},
|
||||
"newAccountCreated2": {
|
||||
"message": "Your new account has been created!"
|
||||
},
|
||||
"youHaveBeenLoggedIn": {
|
||||
"message": "You have been logged in!"
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "تم إنشاء الحساب بنجاح."
|
||||
},
|
||||
@@ -4983,6 +4989,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewSend": {
|
||||
"message": "View Send",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"viewSendHiddenEmailWarning": {
|
||||
"message": "The Bitwarden user who created this Send has chosen to hide their email address. You should ensure you trust the source of this link before using or downloading its content.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
@@ -9008,5 +9018,12 @@
|
||||
},
|
||||
"secretsManagerWithFreePasswordManagerInfo": {
|
||||
"message": "Your complementary one year Password Manager subscription will upgrade to the selected plan. You will not be charged until the complimentary period is over."
|
||||
},
|
||||
"publicApi": {
|
||||
"message": "Public API",
|
||||
"description": "The text, 'API', is an acronymn and should not be translated."
|
||||
},
|
||||
"additionalContentAvailable": {
|
||||
"message": "Additional content is available"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,6 +964,12 @@
|
||||
"newAccountCreated": {
|
||||
"message": "Yeni hesabınız yaradıldı! İndi giriş edə bilərsiniz."
|
||||
},
|
||||
"newAccountCreated2": {
|
||||
"message": "Your new account has been created!"
|
||||
},
|
||||
"youHaveBeenLoggedIn": {
|
||||
"message": "You have been logged in!"
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "Hesab uğurla yaradıldı."
|
||||
},
|
||||
@@ -4983,6 +4989,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewSend": {
|
||||
"message": "\"Send\"ə bax",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"viewSendHiddenEmailWarning": {
|
||||
"message": "Bu \"Send\"i yaradan Bitwarden istifadəçisi e-poçt ünvanını gizlətməyi seçib. İstifadə etməzdən və ya endirməzdən əvvəl bu keçidin mənbəyinin etibarlı olduğuna əmin olmalısınız.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
@@ -9008,5 +9018,12 @@
|
||||
},
|
||||
"secretsManagerWithFreePasswordManagerInfo": {
|
||||
"message": "Tamamlayıcı bir illik Parol Meneceri abunəliyiniz seçilmiş plana yüksəldiləcək. Ödənişsiz dövr bitənə qədər sizdən ödəniş alınmayacaq."
|
||||
},
|
||||
"publicApi": {
|
||||
"message": "Hər kəsə açıq API",
|
||||
"description": "The text, 'API', is an acronymn and should not be translated."
|
||||
},
|
||||
"additionalContentAvailable": {
|
||||
"message": "Additional content is available"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -964,6 +964,12 @@
|
||||
"newAccountCreated": {
|
||||
"message": "Ваш уліковы запіс створаны! Цяпер вы можаце ўвайсці ў яго."
|
||||
},
|
||||
"newAccountCreated2": {
|
||||
"message": "Your new account has been created!"
|
||||
},
|
||||
"youHaveBeenLoggedIn": {
|
||||
"message": "You have been logged in!"
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "Уліковы запіс паспяхова створаны."
|
||||
},
|
||||
@@ -4983,6 +4989,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewSend": {
|
||||
"message": "View Send",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"viewSendHiddenEmailWarning": {
|
||||
"message": "Карыстальнік Bitwarden, які стварыў гэты Send, вырашыў схаваць сваю электронную пошту. Пераканайцеся, што гэта спасылка атрымана з надзейных крыніц і толькі пасля гэтага выкарыстоўвайце або пампуйце дадзенае змесціва.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
@@ -9008,5 +9018,12 @@
|
||||
},
|
||||
"secretsManagerWithFreePasswordManagerInfo": {
|
||||
"message": "Your complementary one year Password Manager subscription will upgrade to the selected plan. You will not be charged until the complimentary period is over."
|
||||
},
|
||||
"publicApi": {
|
||||
"message": "Public API",
|
||||
"description": "The text, 'API', is an acronymn and should not be translated."
|
||||
},
|
||||
"additionalContentAvailable": {
|
||||
"message": "Additional content is available"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
}
|
||||
},
|
||||
"showMatchDetection": {
|
||||
"message": "Show match detection $WEBSITE$",
|
||||
"message": "Показване на откритото съвпадение $WEBSITE$",
|
||||
"placeholders": {
|
||||
"website": {
|
||||
"content": "$1",
|
||||
@@ -96,7 +96,7 @@
|
||||
}
|
||||
},
|
||||
"hideMatchDetection": {
|
||||
"message": "Hide match detection $WEBSITE$",
|
||||
"message": "Скриване на откритото съвпадение $WEBSITE$",
|
||||
"placeholders": {
|
||||
"website": {
|
||||
"content": "$1",
|
||||
@@ -964,6 +964,12 @@
|
||||
"newAccountCreated": {
|
||||
"message": "Абонаментът ви бе създаден. Вече можете да се впишете."
|
||||
},
|
||||
"newAccountCreated2": {
|
||||
"message": "Новата Ви регистрация беше създадена!"
|
||||
},
|
||||
"youHaveBeenLoggedIn": {
|
||||
"message": "Вече сте вписан(а)!"
|
||||
},
|
||||
"trialAccountCreated": {
|
||||
"message": "Регистрацията е създадена успешно."
|
||||
},
|
||||
@@ -4983,6 +4989,10 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"viewSend": {
|
||||
"message": "Преглед на изпращането",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
},
|
||||
"viewSendHiddenEmailWarning": {
|
||||
"message": "Потребителят, който е създал това изпращане, е избрал да скрие адреса на своята е-поща. Уверете се, че източникът на тази връзка е достоверен, преди да я последвате или да свалите съдържание чрез нея.",
|
||||
"description": "'Send' is a noun and the name of a feature called 'Bitwarden Send'. It should not be translated."
|
||||
@@ -5653,7 +5663,7 @@
|
||||
"message": "Free Bitwarden Families offer successfully redeemed"
|
||||
},
|
||||
"redeemed": {
|
||||
"message": "Redeemed"
|
||||
"message": "Използван"
|
||||
},
|
||||
"redeemedAccount": {
|
||||
"message": "Регистрацията е присвоена"
|
||||
@@ -6875,7 +6885,7 @@
|
||||
"description": "Label for the expiration date of an access token."
|
||||
},
|
||||
"canRead": {
|
||||
"message": "Can read",
|
||||
"message": "Може да чете",
|
||||
"description": "Label for the access level of an access token (Read only)."
|
||||
},
|
||||
"accessTokensNoItemsTitle": {
|
||||
@@ -7200,7 +7210,7 @@
|
||||
"message": "Member status filter"
|
||||
},
|
||||
"inviteMember": {
|
||||
"message": "Invite member"
|
||||
"message": "Покана на член"
|
||||
},
|
||||
"needsConfirmation": {
|
||||
"message": "Изисква потвърждение"
|
||||
@@ -9008,5 +9018,12 @@
|
||||
},
|
||||
"secretsManagerWithFreePasswordManagerInfo": {
|
||||
"message": "Your complementary one year Password Manager subscription will upgrade to the selected plan. You will not be charged until the complimentary period is over."
|
||||
},
|
||||
"publicApi": {
|
||||
"message": "Публичен ППИ",
|
||||
"description": "The text, 'API', is an acronymn and should not be translated."
|
||||
},
|
||||
"additionalContentAvailable": {
|
||||
"message": "Има налично допълнително съдържание"
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user