mirror of
https://github.com/bitwarden/browser
synced 2025-12-17 00:33:44 +00:00
[PM-24011] Add handler for new policy sync push notification (#17465)
* add handler for new policy sync push notification * fix story book build failure * move logic into policy service, fix tests * add account service * add missing service to clie
This commit is contained in:
@@ -3,6 +3,7 @@ import { BehaviorSubject, bufferCount, firstValueFrom, Subject, ObservedValueOf
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { AuthRequestAnsweringServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-answering/auth-request-answering.service.abstraction";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
|
||||
@@ -34,6 +35,7 @@ describe("DefaultServerNotificationsService (multi-user)", () => {
|
||||
let webPushNotificationConnectionService: MockProxy<WebPushConnectionService>;
|
||||
let authRequestAnsweringService: MockProxy<AuthRequestAnsweringServiceAbstraction>;
|
||||
let configService: MockProxy<ConfigService>;
|
||||
let policyService: MockProxy<InternalPolicyService>;
|
||||
|
||||
let activeUserAccount$: BehaviorSubject<ObservedValueOf<AccountService["activeAccount$"]>>;
|
||||
let userAccounts$: BehaviorSubject<ObservedValueOf<AccountService["accounts$"]>>;
|
||||
@@ -136,6 +138,8 @@ describe("DefaultServerNotificationsService (multi-user)", () => {
|
||||
return new BehaviorSubject(flagValueByFlag[flag] ?? false) as any;
|
||||
});
|
||||
|
||||
policyService = mock<InternalPolicyService>();
|
||||
|
||||
defaultServerNotificationsService = new DefaultServerNotificationsService(
|
||||
mock<LogService>(),
|
||||
syncService,
|
||||
@@ -149,6 +153,7 @@ describe("DefaultServerNotificationsService (multi-user)", () => {
|
||||
webPushNotificationConnectionService,
|
||||
authRequestAnsweringService,
|
||||
configService,
|
||||
policyService,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,8 @@ import { BehaviorSubject, bufferCount, firstValueFrom, ObservedValueOf, of, Subj
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyType } from "@bitwarden/common/admin-console/enums";
|
||||
import { AuthRequestAnsweringServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-answering/auth-request-answering.service.abstraction";
|
||||
|
||||
import { awaitAsync } from "../../../../spec";
|
||||
@@ -42,6 +44,7 @@ describe("NotificationsService", () => {
|
||||
let webPushNotificationConnectionService: MockProxy<WebPushConnectionService>;
|
||||
let authRequestAnsweringService: MockProxy<AuthRequestAnsweringServiceAbstraction>;
|
||||
let configService: MockProxy<ConfigService>;
|
||||
let policyService: MockProxy<InternalPolicyService>;
|
||||
|
||||
let activeAccount: BehaviorSubject<ObservedValueOf<AccountService["activeAccount$"]>>;
|
||||
let accounts: BehaviorSubject<ObservedValueOf<AccountService["accounts$"]>>;
|
||||
@@ -71,6 +74,7 @@ describe("NotificationsService", () => {
|
||||
webPushNotificationConnectionService = mock<WorkerWebPushConnectionService>();
|
||||
authRequestAnsweringService = mock<AuthRequestAnsweringServiceAbstraction>();
|
||||
configService = mock<ConfigService>();
|
||||
policyService = mock<InternalPolicyService>();
|
||||
|
||||
// For these tests, use the active-user implementation (feature flag disabled)
|
||||
configService.getFeatureFlag$.mockImplementation(() => of(true));
|
||||
@@ -123,6 +127,7 @@ describe("NotificationsService", () => {
|
||||
webPushNotificationConnectionService,
|
||||
authRequestAnsweringService,
|
||||
configService,
|
||||
policyService,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -391,5 +396,67 @@ describe("NotificationsService", () => {
|
||||
expect(logoutCallback).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("NotificationType.SyncPolicy", () => {
|
||||
it("should call policyService.syncPolicy with the policy from the notification", async () => {
|
||||
const mockPolicy = {
|
||||
id: "policy-id",
|
||||
organizationId: "org-id",
|
||||
type: PolicyType.TwoFactorAuthentication,
|
||||
enabled: true,
|
||||
data: { test: "data" },
|
||||
};
|
||||
|
||||
policyService.syncPolicy.mockResolvedValue();
|
||||
|
||||
const notification = new NotificationResponse({
|
||||
type: NotificationType.SyncPolicy,
|
||||
payload: { policy: mockPolicy },
|
||||
contextId: "different-app-id",
|
||||
});
|
||||
|
||||
await sut["processNotification"](notification, mockUser1);
|
||||
|
||||
expect(policyService.syncPolicy).toHaveBeenCalledTimes(1);
|
||||
expect(policyService.syncPolicy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: mockPolicy.id,
|
||||
organizationId: mockPolicy.organizationId,
|
||||
type: mockPolicy.type,
|
||||
enabled: mockPolicy.enabled,
|
||||
data: mockPolicy.data,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("should handle SyncPolicy notification with minimal policy data", async () => {
|
||||
const mockPolicy = {
|
||||
id: "policy-id-2",
|
||||
organizationId: "org-id-2",
|
||||
type: PolicyType.RequireSso,
|
||||
enabled: false,
|
||||
};
|
||||
|
||||
policyService.syncPolicy.mockResolvedValue();
|
||||
|
||||
const notification = new NotificationResponse({
|
||||
type: NotificationType.SyncPolicy,
|
||||
payload: { policy: mockPolicy },
|
||||
contextId: "different-app-id",
|
||||
});
|
||||
|
||||
await sut["processNotification"](notification, mockUser1);
|
||||
|
||||
expect(policyService.syncPolicy).toHaveBeenCalledTimes(1);
|
||||
expect(policyService.syncPolicy).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: mockPolicy.id,
|
||||
organizationId: mockPolicy.organizationId,
|
||||
type: mockPolicy.type,
|
||||
enabled: mockPolicy.enabled,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
// This import has been flagged as unallowed for this class. It may be involved in a circular dependency loop.
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import { LogoutReason } from "@bitwarden/auth/common";
|
||||
import { InternalPolicyService } from "@bitwarden/common/admin-console/abstractions/policy/policy.service.abstraction";
|
||||
import { PolicyData } from "@bitwarden/common/admin-console/models/data/policy.data";
|
||||
import { AuthRequestAnsweringServiceAbstraction } from "@bitwarden/common/auth/abstractions/auth-request-answering/auth-request-answering.service.abstraction";
|
||||
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
|
||||
import { trackedMerge } from "@bitwarden/common/platform/misc";
|
||||
@@ -67,6 +69,7 @@ export class DefaultServerNotificationsService implements ServerNotificationsSer
|
||||
private readonly webPushConnectionService: WebPushConnectionService,
|
||||
private readonly authRequestAnsweringService: AuthRequestAnsweringServiceAbstraction,
|
||||
private readonly configService: ConfigService,
|
||||
private readonly policyService: InternalPolicyService,
|
||||
) {
|
||||
this.notifications$ = this.configService
|
||||
.getFeatureFlag$(FeatureFlag.InactiveUserServerNotification)
|
||||
@@ -330,6 +333,9 @@ export class DefaultServerNotificationsService implements ServerNotificationsSer
|
||||
adminId: notification.payload.adminId,
|
||||
});
|
||||
break;
|
||||
case NotificationType.SyncPolicy:
|
||||
await this.policyService.syncPolicy(PolicyData.fromPolicy(notification.payload.policy));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user