mirror of
https://github.com/bitwarden/browser
synced 2026-02-10 05:30:01 +00:00
Merge branch 'bitwarden:main' into PM-19521
This commit is contained in:
@@ -45,7 +45,6 @@ import { getUserId } from "@bitwarden/common/auth/services/account.service";
|
||||
import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions";
|
||||
import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-api.service.abstraction";
|
||||
import { EventType } from "@bitwarden/common/enums";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
|
||||
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
|
||||
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
|
||||
@@ -196,7 +195,6 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
private refresh$ = new BehaviorSubject<void>(null);
|
||||
private destroy$ = new Subject<void>();
|
||||
protected addAccessStatus$ = new BehaviorSubject<AddAccessStatusType>(0);
|
||||
private resellerManagedOrgAlert: boolean;
|
||||
private vaultItemDialogRef?: DialogRef<VaultItemDialogResult> | undefined;
|
||||
|
||||
private readonly unpaidSubscriptionDialog$ = this.accountService.activeAccount$.pipe(
|
||||
@@ -264,10 +262,6 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
async ngOnInit() {
|
||||
this.userId = await firstValueFrom(getUserId(this.accountService.activeAccount$));
|
||||
|
||||
this.resellerManagedOrgAlert = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.ResellerManagedOrgAlert,
|
||||
);
|
||||
|
||||
this.trashCleanupWarning = this.i18nService.t(
|
||||
this.platformUtilsService.isSelfHost()
|
||||
? "trashCleanupWarningSelfHosted"
|
||||
@@ -654,7 +648,7 @@ export class VaultComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
|
||||
this.resellerWarning$ = organization$.pipe(
|
||||
filter((org) => org.isOwner && this.resellerManagedOrgAlert),
|
||||
filter((org) => org.isOwner),
|
||||
switchMap((org) =>
|
||||
from(this.billingApiService.getOrganizationBillingMetadata(org.id)).pipe(
|
||||
map((metadata) => ({ org, metadata })),
|
||||
|
||||
@@ -11,8 +11,6 @@ import { BillingSourceResponse } from "@bitwarden/common/billing/models/response
|
||||
import { OrganizationBillingMetadataResponse } from "@bitwarden/common/billing/models/response/organization-billing-metadata.response";
|
||||
import { OrganizationSubscriptionResponse } from "@bitwarden/common/billing/models/response/organization-subscription.response";
|
||||
import { PaymentSourceResponse } from "@bitwarden/common/billing/models/response/payment-source.response";
|
||||
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 { DialogService } from "@bitwarden/components";
|
||||
|
||||
@@ -24,15 +22,12 @@ import { FreeTrial } from "../types/free-trial";
|
||||
|
||||
@Injectable({ providedIn: "root" })
|
||||
export class TrialFlowService {
|
||||
private resellerManagedOrgAlert: boolean;
|
||||
|
||||
constructor(
|
||||
private i18nService: I18nService,
|
||||
protected dialogService: DialogService,
|
||||
private router: Router,
|
||||
protected billingApiService: BillingApiServiceAbstraction,
|
||||
private organizationApiService: OrganizationApiServiceAbstraction,
|
||||
private configService: ConfigService,
|
||||
) {}
|
||||
checkForOrgsWithUpcomingPaymentIssues(
|
||||
organization: Organization,
|
||||
@@ -98,10 +93,6 @@ export class TrialFlowService {
|
||||
isCanceled: boolean,
|
||||
isUnpaid: boolean,
|
||||
): Promise<boolean> {
|
||||
this.resellerManagedOrgAlert = await this.configService.getFeatureFlag(
|
||||
FeatureFlag.ResellerManagedOrgAlert,
|
||||
);
|
||||
|
||||
if (!org?.isOwner && !org.providerId) {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
title: this.i18nService.t("suspendedOrganizationTitle", org?.name),
|
||||
@@ -113,7 +104,7 @@ export class TrialFlowService {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (org.providerId && this.resellerManagedOrgAlert) {
|
||||
if (org.providerId) {
|
||||
await this.dialogService.openSimpleDialog({
|
||||
title: this.i18nService.t("suspendedOrganizationTitle", org.name),
|
||||
content: { key: "suspendedManagedOrgMessage", placeholders: [org.providerName] },
|
||||
@@ -134,7 +125,7 @@ export class TrialFlowService {
|
||||
});
|
||||
}
|
||||
|
||||
if (org.isOwner && isCanceled && this.resellerManagedOrgAlert) {
|
||||
if (org.isOwner && isCanceled) {
|
||||
await this.changePlan(org);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1480,7 +1480,7 @@ const safeProviders: SafeProvider[] = [
|
||||
safeProvider({
|
||||
provide: EndUserNotificationService,
|
||||
useClass: DefaultEndUserNotificationService,
|
||||
deps: [StateProvider, ApiServiceAbstraction],
|
||||
deps: [StateProvider, ApiServiceAbstraction, NotificationsService],
|
||||
}),
|
||||
safeProvider({
|
||||
provide: DeviceTrustToastServiceAbstraction,
|
||||
|
||||
@@ -46,7 +46,6 @@ export enum FeatureFlag {
|
||||
TrialPaymentOptional = "PM-8163-trial-payment",
|
||||
MacOsNativeCredentialSync = "macos-native-credential-sync",
|
||||
PrivateKeyRegeneration = "pm-12241-private-key-regeneration",
|
||||
ResellerManagedOrgAlert = "PM-15814-alert-owners-of-reseller-managed-orgs",
|
||||
AccountDeprovisioningBanner = "pm-17120-account-deprovisioning-admin-console-banner",
|
||||
PM15179_AddExistingOrgsFromProviderPortal = "pm-15179-add-existing-orgs-from-provider-portal",
|
||||
PM12276_BreadcrumbEventLogs = "pm-12276-breadcrumbing-for-business-features",
|
||||
@@ -107,7 +106,6 @@ export const DefaultFeatureFlagValue = {
|
||||
[FeatureFlag.TrialPaymentOptional]: FALSE,
|
||||
[FeatureFlag.MacOsNativeCredentialSync]: FALSE,
|
||||
[FeatureFlag.PrivateKeyRegeneration]: FALSE,
|
||||
[FeatureFlag.ResellerManagedOrgAlert]: FALSE,
|
||||
[FeatureFlag.AccountDeprovisioningBanner]: FALSE,
|
||||
[FeatureFlag.PM15179_AddExistingOrgsFromProviderPortal]: FALSE,
|
||||
[FeatureFlag.PM12276_BreadcrumbEventLogs]: FALSE,
|
||||
|
||||
@@ -24,4 +24,6 @@ export enum NotificationType {
|
||||
SyncOrganizations = 17,
|
||||
SyncOrganizationStatusChanged = 18,
|
||||
SyncOrganizationCollectionSettingChanged = 19,
|
||||
Notification = 20,
|
||||
NotificationStatus = 21,
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { Subscription } from "rxjs";
|
||||
import { Observable, Subject, Subscription } from "rxjs";
|
||||
|
||||
import { NotificationResponse } from "@bitwarden/common/models/response/notification.response";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import { LogService } from "../../abstractions/log.service";
|
||||
import { NotificationsService } from "../notifications.service";
|
||||
|
||||
export class NoopNotificationsService implements NotificationsService {
|
||||
notifications$: Observable<readonly [NotificationResponse, UserId]> = new Subject();
|
||||
|
||||
constructor(private logService: LogService) {}
|
||||
|
||||
startListening(): Subscription {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { Subscription } from "rxjs";
|
||||
import { Observable, Subscription } from "rxjs";
|
||||
|
||||
import { NotificationResponse } from "@bitwarden/common/models/response/notification.response";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
/**
|
||||
* A service offering abilities to interact with push notifications from the server.
|
||||
*/
|
||||
export abstract class NotificationsService {
|
||||
abstract notifications$: Observable<readonly [NotificationResponse, UserId]>;
|
||||
/**
|
||||
* Starts automatic listening and processing of notifications, should only be called once per application,
|
||||
* or you will risk notifications being processed multiple times.
|
||||
|
||||
@@ -34,13 +34,6 @@ export abstract class EndUserNotificationService {
|
||||
*/
|
||||
abstract markAsDeleted(notificationId: any, userId: UserId): Promise<void>;
|
||||
|
||||
/**
|
||||
* Create/update a notification in the state for the user specified within the notification.
|
||||
* @remarks This method should only be called when a notification payload is received from the web socket.
|
||||
* @param notification
|
||||
*/
|
||||
abstract upsert(notification: Notification): Promise<void>;
|
||||
|
||||
/**
|
||||
* Clear all notifications from state for the given user.
|
||||
* @param userId
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { TestBed } from "@angular/core/testing";
|
||||
import { firstValueFrom } from "rxjs";
|
||||
import { firstValueFrom, of } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { NotificationId, UserId } from "@bitwarden/common/types/guid";
|
||||
import { DefaultEndUserNotificationService } from "@bitwarden/vault";
|
||||
@@ -36,6 +37,12 @@ describe("End User Notification Center Service", () => {
|
||||
send: mockApiSend,
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: NotificationsService,
|
||||
useValue: {
|
||||
notifications$: of(null),
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { map, Observable, switchMap } from "rxjs";
|
||||
import { concatMap, filter, map, Observable, switchMap } from "rxjs";
|
||||
|
||||
import { ApiService } from "@bitwarden/common/abstractions/api.service";
|
||||
import { NotificationType } from "@bitwarden/common/enums";
|
||||
import { ListResponse } from "@bitwarden/common/models/response/list.response";
|
||||
import { NotificationsService } from "@bitwarden/common/platform/notifications";
|
||||
import { StateProvider } from "@bitwarden/common/platform/state";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
@@ -14,12 +16,30 @@ import { NOTIFICATIONS } from "../state/end-user-notification.state";
|
||||
/**
|
||||
* A service for retrieving and managing notifications for end users.
|
||||
*/
|
||||
@Injectable()
|
||||
@Injectable({
|
||||
providedIn: "root",
|
||||
})
|
||||
export class DefaultEndUserNotificationService implements EndUserNotificationService {
|
||||
constructor(
|
||||
private stateProvider: StateProvider,
|
||||
private apiService: ApiService,
|
||||
) {}
|
||||
private defaultNotifications: NotificationsService,
|
||||
) {
|
||||
this.defaultNotifications.notifications$
|
||||
.pipe(
|
||||
filter(
|
||||
([notification]) =>
|
||||
notification.type === NotificationType.Notification ||
|
||||
notification.type === NotificationType.NotificationStatus,
|
||||
),
|
||||
concatMap(([notification, userId]) =>
|
||||
this.updateNotificationState(userId, [
|
||||
new NotificationViewData(notification.payload as NotificationViewResponse),
|
||||
]),
|
||||
),
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
notifications$ = perUserCache$((userId: UserId): Observable<NotificationView[]> => {
|
||||
return this.notificationState(userId).state$.pipe(
|
||||
@@ -58,8 +78,6 @@ export class DefaultEndUserNotificationService implements EndUserNotificationSer
|
||||
await this.getNotifications(userId);
|
||||
}
|
||||
|
||||
upsert(notification: Notification): any {}
|
||||
|
||||
async clearState(userId: UserId): Promise<void> {
|
||||
await this.updateNotificationState(userId, []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user