mirror of
https://github.com/bitwarden/browser
synced 2025-12-20 10:13:31 +00:00
* Use account service to track accounts and active account * Remove state service active account Observables. * Add email verified to account service * Do not store account info on logged out accounts * Add account activity tracking to account service * Use last account activity from account service * migrate or replicate account service data * Add `AccountActivityService` that handles storing account last active data * Move active and next active user to account service * Remove authenticated accounts from state object * Fold account activity into account service * Fix builds * Fix desktop app switch * Fix logging out non active user * Expand helper to handle new authenticated accounts location * Prefer view observable to tons of async pipes * Fix `npm run test:types` * Correct user activity sorting test * Be more precise about log out messaging * Fix dev compare errors All stored values are serializable, the next step wasn't necessary and was erroring on some types that lack `toString`. * If the account in unlocked on load of lock component, navigate away from lock screen * Handle no users case for auth service statuses * Specify account to switch to * Filter active account out of inactive accounts * Prefer constructor init * Improve comparator * Use helper methods internally * Fixup component tests * Clarify name * Ensure accounts object has only valid userIds * Capitalize const values * Prefer descriptive, single-responsibility guards * Update libs/common/src/state-migrations/migrate.ts Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com> * Fix merge * Add user Id validation activity for undefined was being set, which was resulting in requests for the auth status of `"undefined"` (string) userId, due to key enumeration. These changes stop that at both locations, as well as account add for good measure. --------- Co-authored-by: Justin Baur <19896123+justindbaur@users.noreply.github.com>
94 lines
2.8 KiB
TypeScript
94 lines
2.8 KiB
TypeScript
import { Observable } from "rxjs";
|
|
|
|
import { UserId } from "../../types/guid";
|
|
|
|
/**
|
|
* Holds information about an account for use in the AccountService
|
|
* if more information is added, be sure to update the equality method.
|
|
*/
|
|
export type AccountInfo = {
|
|
email: string;
|
|
emailVerified: boolean;
|
|
name: string | undefined;
|
|
};
|
|
|
|
export function accountInfoEqual(a: AccountInfo, b: AccountInfo) {
|
|
if (a == null && b == null) {
|
|
return true;
|
|
}
|
|
|
|
if (a == null || b == null) {
|
|
return false;
|
|
}
|
|
|
|
const keys = new Set([...Object.keys(a), ...Object.keys(b)]) as Set<keyof AccountInfo>;
|
|
for (const key of keys) {
|
|
if (a[key] !== b[key]) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
export abstract class AccountService {
|
|
accounts$: Observable<Record<UserId, AccountInfo>>;
|
|
activeAccount$: Observable<{ id: UserId | undefined } & AccountInfo>;
|
|
|
|
/**
|
|
* Observable of the last activity time for each account.
|
|
*/
|
|
accountActivity$: Observable<Record<UserId, Date>>;
|
|
/** Account list in order of descending recency */
|
|
sortedUserIds$: Observable<UserId[]>;
|
|
/** Next account that is not the current active account */
|
|
nextUpAccount$: Observable<{ id: UserId } & AccountInfo>;
|
|
/**
|
|
* Updates the `accounts$` observable with the new account data.
|
|
*
|
|
* @note Also sets the last active date of the account to `now`.
|
|
* @param userId
|
|
* @param accountData
|
|
*/
|
|
abstract addAccount(userId: UserId, accountData: AccountInfo): Promise<void>;
|
|
/**
|
|
* updates the `accounts$` observable with the new preferred name for the account.
|
|
* @param userId
|
|
* @param name
|
|
*/
|
|
abstract setAccountName(userId: UserId, name: string): Promise<void>;
|
|
/**
|
|
* updates the `accounts$` observable with the new email for the account.
|
|
* @param userId
|
|
* @param email
|
|
*/
|
|
abstract setAccountEmail(userId: UserId, email: string): Promise<void>;
|
|
/**
|
|
* updates the `accounts$` observable with the new email verification status for the account.
|
|
* @param userId
|
|
* @param emailVerified
|
|
*/
|
|
abstract setAccountEmailVerified(userId: UserId, emailVerified: boolean): Promise<void>;
|
|
/**
|
|
* Updates the `activeAccount$` observable with the new active account.
|
|
* @param userId
|
|
*/
|
|
abstract switchAccount(userId: UserId): Promise<void>;
|
|
/**
|
|
* Cleans personal information for the given account from the `accounts$` observable. Does not remove the userId from the observable.
|
|
*
|
|
* @note Also sets the last active date of the account to `null`.
|
|
* @param userId
|
|
*/
|
|
abstract clean(userId: UserId): Promise<void>;
|
|
/**
|
|
* Updates the given user's last activity time.
|
|
* @param userId
|
|
* @param lastActivity
|
|
*/
|
|
abstract setAccountActivity(userId: UserId, lastActivity: Date): Promise<void>;
|
|
}
|
|
|
|
export abstract class InternalAccountService extends AccountService {
|
|
abstract delete(): void;
|
|
}
|