1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-15 07:43:35 +00:00

[PM-11136] Convert LoginEmailService email property to state provider (#10624)

* convert email property to state provider

* update tests

* assign loginEmail to variable before passing in

* remove nav logic in ngOnInit
This commit is contained in:
rr-bw
2024-09-03 09:40:11 -07:00
committed by GitHub
parent ea618c682a
commit b27dc44298
11 changed files with 58 additions and 54 deletions

View File

@@ -1,29 +1,28 @@
import { Observable } from "rxjs";
export abstract class LoginEmailServiceAbstraction {
/**
* An observable that monitors the loginEmail in memory.
* The loginEmail is the email that is being used in the current login process.
*/
loginEmail$: Observable<string | null>;
/**
* An observable that monitors the storedEmail on disk.
* This will return null if an account is being added.
*/
storedEmail$: Observable<string | null>;
/**
* Gets the current email being used in the login process from memory.
* @returns A string of the email.
* Sets the loginEmail in memory.
* The loginEmail is the email that is being used in the current login process.
*/
getEmail: () => string;
/**
* Sets the current email being used in the login process in memory.
* @param email The email to be set.
*/
setEmail: (email: string) => void;
setLoginEmail: (email: string) => Promise<void>;
/**
* Gets from memory whether or not the email should be stored on disk when `saveEmailSettings` is called.
* @returns A boolean stating whether or not the email should be stored on disk.
*/
getRememberEmail: () => boolean;
/**
* Sets in memory whether or not the email should be stored on disk when
* `saveEmailSettings` is called.
* Sets in memory whether or not the email should be stored on disk when `saveEmailSettings` is called.
*/
setRememberEmail: (value: boolean) => void;
/**

View File

@@ -43,7 +43,7 @@ describe("LoginEmailService", () => {
describe("storedEmail$", () => {
it("returns the stored email when not adding an account", async () => {
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
@@ -53,7 +53,7 @@ describe("LoginEmailService", () => {
});
it("returns the stored email when not adding an account and the user has just logged in", async () => {
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
@@ -66,7 +66,7 @@ describe("LoginEmailService", () => {
});
it("returns null when adding an account", async () => {
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
@@ -83,7 +83,7 @@ describe("LoginEmailService", () => {
describe("saveEmailSettings", () => {
it("saves the email when not adding an account", async () => {
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
@@ -95,7 +95,7 @@ describe("LoginEmailService", () => {
it("clears the email when not adding an account and rememberEmail is false", async () => {
storedEmailState.stateSubject.next("initialEmail@bitwarden.com");
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(false);
await sut.saveEmailSettings();
@@ -110,7 +110,7 @@ describe("LoginEmailService", () => {
["OtherUserId" as UserId]: AuthenticationStatus.Locked,
});
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
@@ -127,7 +127,7 @@ describe("LoginEmailService", () => {
["OtherUserId" as UserId]: AuthenticationStatus.Locked,
});
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(false);
await sut.saveEmailSettings();
@@ -140,11 +140,11 @@ describe("LoginEmailService", () => {
it("does not clear the email and rememberEmail after saving", async () => {
// Browser uses these values to maintain the email between login and 2fa components so
// we do not want to clear them too early.
sut.setEmail("userEmail@bitwarden.com");
await sut.setLoginEmail("userEmail@bitwarden.com");
sut.setRememberEmail(true);
await sut.saveEmailSettings();
const result = sut.getEmail();
const result = await firstValueFrom(sut.loginEmail$);
expect(result).toBe("userEmail@bitwarden.com");
});

View File

@@ -8,21 +8,28 @@ import {
GlobalState,
KeyDefinition,
LOGIN_EMAIL_DISK,
LOGIN_EMAIL_MEMORY,
StateProvider,
} from "../../../../../common/src/platform/state";
import { LoginEmailServiceAbstraction } from "../../abstractions/login-email.service";
export const LOGIN_EMAIL = new KeyDefinition<string>(LOGIN_EMAIL_MEMORY, "loginEmail", {
deserializer: (value: string) => value,
});
export const STORED_EMAIL = new KeyDefinition<string>(LOGIN_EMAIL_DISK, "storedEmail", {
deserializer: (value: string) => value,
});
export class LoginEmailService implements LoginEmailServiceAbstraction {
private email: string | null;
private rememberEmail: boolean;
// True if an account is currently being added through account switching
private readonly addingAccount$: Observable<boolean>;
private readonly loginEmailState: GlobalState<string>;
loginEmail$: Observable<string | null>;
private readonly storedEmailState: GlobalState<string>;
storedEmail$: Observable<string | null>;
@@ -31,6 +38,7 @@ export class LoginEmailService implements LoginEmailServiceAbstraction {
private authService: AuthService,
private stateProvider: StateProvider,
) {
this.loginEmailState = this.stateProvider.getGlobal(LOGIN_EMAIL);
this.storedEmailState = this.stateProvider.getGlobal(STORED_EMAIL);
// In order to determine if an account is being added, we check if any account is not logged out
@@ -46,6 +54,8 @@ export class LoginEmailService implements LoginEmailServiceAbstraction {
}),
);
this.loginEmail$ = this.loginEmailState.state$;
this.storedEmail$ = this.storedEmailState.state$.pipe(
switchMap(async (storedEmail) => {
// When adding an account, we don't show the stored email
@@ -57,12 +67,8 @@ export class LoginEmailService implements LoginEmailServiceAbstraction {
);
}
getEmail() {
return this.email;
}
setEmail(email: string) {
this.email = email;
async setLoginEmail(email: string) {
await this.loginEmailState.update((_) => email);
}
getRememberEmail() {
@@ -76,25 +82,27 @@ export class LoginEmailService implements LoginEmailServiceAbstraction {
// Note: only clear values on successful login or you are sure they are not needed.
// Browser uses these values to maintain the email between login and 2fa components so
// we do not want to clear them too early.
clearValues() {
this.email = null;
async clearValues() {
await this.setLoginEmail(null);
this.rememberEmail = false;
}
async saveEmailSettings() {
const addingAccount = await firstValueFrom(this.addingAccount$);
const email = await firstValueFrom(this.loginEmail$);
await this.storedEmailState.update((storedEmail) => {
// If we're adding an account, only overwrite the stored email when rememberEmail is true
if (addingAccount) {
if (this.rememberEmail) {
return this.email;
return email;
}
return storedEmail;
}
// Saving with rememberEmail set to false will clear the stored email
if (this.rememberEmail) {
return this.email;
return email;
}
return null;
});