mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-21 16:18:28 +01:00
[PM-14219] Add service for new device verification notice (#11988)
* added service and spec file for new device verification notice
This commit is contained in:
parent
140a514be3
commit
21855595c5
@ -173,3 +173,7 @@ export const PREMIUM_BANNER_DISK_LOCAL = new StateDefinition("premiumBannerRepro
|
||||
});
|
||||
export const BANNERS_DISMISSED_DISK = new StateDefinition("bannersDismissed", "disk");
|
||||
export const VAULT_BROWSER_UI_ONBOARDING = new StateDefinition("vaultBrowserUiOnboarding", "disk");
|
||||
export const NEW_DEVICE_VERIFICATION_NOTICE = new StateDefinition(
|
||||
"newDeviceVerificationNotice",
|
||||
"disk",
|
||||
);
|
||||
|
@ -0,0 +1,85 @@
|
||||
import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { Utils } from "@bitwarden/common/platform/misc/utils";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
import {
|
||||
FakeAccountService,
|
||||
FakeSingleUserState,
|
||||
FakeStateProvider,
|
||||
mockAccountServiceWith,
|
||||
} from "../../../common/spec";
|
||||
|
||||
import {
|
||||
NewDeviceVerificationNoticeService,
|
||||
NewDeviceVerificationNotice,
|
||||
NEW_DEVICE_VERIFICATION_NOTICE_KEY,
|
||||
} from "./new-device-verification-notice.service";
|
||||
|
||||
describe("New Device Verification Notice", () => {
|
||||
const sut = NEW_DEVICE_VERIFICATION_NOTICE_KEY;
|
||||
const userId = Utils.newGuid() as UserId;
|
||||
let newDeviceVerificationService: NewDeviceVerificationNoticeService;
|
||||
let mockNoticeState: FakeSingleUserState<NewDeviceVerificationNotice>;
|
||||
let stateProvider: FakeStateProvider;
|
||||
let accountService: FakeAccountService;
|
||||
|
||||
beforeEach(() => {
|
||||
accountService = mockAccountServiceWith(userId);
|
||||
stateProvider = new FakeStateProvider(accountService);
|
||||
mockNoticeState = stateProvider.singleUser.getFake(userId, NEW_DEVICE_VERIFICATION_NOTICE_KEY);
|
||||
newDeviceVerificationService = new NewDeviceVerificationNoticeService(stateProvider);
|
||||
});
|
||||
|
||||
it("should deserialize newDeviceVerificationNotice values", async () => {
|
||||
const currentDate = new Date();
|
||||
const inputObj = {
|
||||
last_dismissal: currentDate,
|
||||
permanent_dismissal: false,
|
||||
};
|
||||
|
||||
const expectedFolderData = {
|
||||
last_dismissal: currentDate.toJSON(),
|
||||
permanent_dismissal: false,
|
||||
};
|
||||
|
||||
const result = sut.deserializer(JSON.parse(JSON.stringify(inputObj)));
|
||||
|
||||
expect(result).toEqual(expectedFolderData);
|
||||
});
|
||||
|
||||
describe("notice$", () => {
|
||||
it("emits new device verification notice state", async () => {
|
||||
const currentDate = new Date();
|
||||
const data = {
|
||||
last_dismissal: currentDate,
|
||||
permanent_dismissal: false,
|
||||
};
|
||||
await stateProvider.setUserState(NEW_DEVICE_VERIFICATION_NOTICE_KEY, data, userId);
|
||||
|
||||
const result = await firstValueFrom(newDeviceVerificationService.noticeState$(userId));
|
||||
|
||||
expect(result).toBe(data);
|
||||
});
|
||||
});
|
||||
|
||||
describe("update notice state", () => {
|
||||
it("should update the date with a new value", async () => {
|
||||
const currentDate = new Date();
|
||||
const oldDate = new Date("11-11-2011");
|
||||
const oldState = {
|
||||
last_dismissal: oldDate,
|
||||
permanent_dismissal: false,
|
||||
};
|
||||
const newState = {
|
||||
last_dismissal: currentDate,
|
||||
permanent_dismissal: true,
|
||||
};
|
||||
mockNoticeState.nextState(oldState);
|
||||
await newDeviceVerificationService.updateNewDeviceVerificationNoticeState(userId, newState);
|
||||
|
||||
const result = await firstValueFrom(newDeviceVerificationService.noticeState$(userId));
|
||||
expect(result).toEqual(newState);
|
||||
});
|
||||
});
|
||||
});
|
@ -0,0 +1,65 @@
|
||||
import { Injectable } from "@angular/core";
|
||||
import { Observable } from "rxjs";
|
||||
import { Jsonify } from "type-fest";
|
||||
|
||||
import {
|
||||
StateProvider,
|
||||
UserKeyDefinition,
|
||||
NEW_DEVICE_VERIFICATION_NOTICE,
|
||||
SingleUserState,
|
||||
} from "@bitwarden/common/platform/state";
|
||||
import { UserId } from "@bitwarden/common/types/guid";
|
||||
|
||||
// This service checks when to show New Device Verification Notice to Users
|
||||
// It will be a two phase approach and the values below will work with two different feature flags
|
||||
// If a user dismisses the notice, use "last_dismissal" to wait 7 days before re-prompting
|
||||
// permanent_dismissal will be checked if the user should never see the notice again
|
||||
export class NewDeviceVerificationNotice {
|
||||
last_dismissal: Date;
|
||||
permanent_dismissal: boolean;
|
||||
|
||||
constructor(obj: Partial<NewDeviceVerificationNotice>) {
|
||||
if (obj == null) {
|
||||
return;
|
||||
}
|
||||
this.last_dismissal = obj.last_dismissal || null;
|
||||
this.permanent_dismissal = obj.permanent_dismissal || null;
|
||||
}
|
||||
|
||||
static fromJSON(obj: Jsonify<NewDeviceVerificationNotice>) {
|
||||
return Object.assign(new NewDeviceVerificationNotice({}), obj);
|
||||
}
|
||||
}
|
||||
|
||||
export const NEW_DEVICE_VERIFICATION_NOTICE_KEY =
|
||||
new UserKeyDefinition<NewDeviceVerificationNotice>(
|
||||
NEW_DEVICE_VERIFICATION_NOTICE,
|
||||
"noticeState",
|
||||
{
|
||||
deserializer: (obj: Jsonify<NewDeviceVerificationNotice>) =>
|
||||
NewDeviceVerificationNotice.fromJSON(obj),
|
||||
clearOn: [],
|
||||
},
|
||||
);
|
||||
|
||||
@Injectable()
|
||||
export class NewDeviceVerificationNoticeService {
|
||||
constructor(private stateProvider: StateProvider) {}
|
||||
|
||||
private noticeState(userId: UserId): SingleUserState<NewDeviceVerificationNotice> {
|
||||
return this.stateProvider.getUser(userId, NEW_DEVICE_VERIFICATION_NOTICE_KEY);
|
||||
}
|
||||
|
||||
noticeState$(userId: UserId): Observable<NewDeviceVerificationNotice> {
|
||||
return this.noticeState(userId).state$;
|
||||
}
|
||||
|
||||
async updateNewDeviceVerificationNoticeState(
|
||||
userId: UserId,
|
||||
newState: NewDeviceVerificationNotice,
|
||||
): Promise<void> {
|
||||
await this.noticeState(userId).update(() => {
|
||||
return { ...newState };
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user