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:
@@ -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;
|
||||
/**
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user