1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-01-31 22:51:28 +01:00

Define account service observable responsibilities

This commit is contained in:
Matt Gibson 2023-09-26 14:55:26 -04:00 committed by Justin Baur
parent 5e8feb22d0
commit 0a9c8a416a
No known key found for this signature in database
GPG Key ID: 46438BBD28B69008
4 changed files with 124 additions and 1 deletions

View File

@ -1,4 +1,16 @@
export abstract class AccountService {}
import { Observable } from "rxjs";
import { UserId } from "../../types/guid";
import { AuthenticationStatus } from "../enums/authentication-status";
export abstract class AccountService {
accounts$: Observable<Record<UserId, AuthenticationStatus>>;
activeAccount$: Observable<{ id: UserId | undefined; status: AuthenticationStatus | undefined }>;
accountLock$: Observable<UserId>;
accountLogout$: Observable<UserId>;
abstract setAccountStatus(userId: UserId, status: AuthenticationStatus): void;
abstract switchAccount(userId: UserId): void;
}
export abstract class InternalAccountService extends AccountService {
abstract delete(): void;

View File

@ -1,10 +1,43 @@
import { BehaviorSubject, Subject } from "rxjs";
import { InternalAccountService } from "../../auth/abstractions/account.service";
import { LogService } from "../../platform/abstractions/log.service";
import { MessagingService } from "../../platform/abstractions/messaging.service";
import { UserId } from "../../types/guid";
import { AuthenticationStatus } from "../enums/authentication-status";
export class AccountServiceImplementation implements InternalAccountService {
private accounts = new BehaviorSubject<Record<UserId, AuthenticationStatus>>({});
private activeAccount = new BehaviorSubject<{
id: UserId | undefined;
status: AuthenticationStatus | undefined;
}>({ id: undefined, status: undefined });
private lock = new Subject<UserId>();
private logout = new Subject<UserId>();
accounts$ = this.accounts.asObservable();
activeAccount$ = this.activeAccount.asObservable();
accountLock$ = this.lock.asObservable();
accountLogout$ = this.logout.asObservable();
constructor(private messagingService: MessagingService, private logService: LogService) {}
setAccountStatus(userId: UserId, status: AuthenticationStatus): void {
this.accounts.value[userId] = status;
this.accounts.next(this.accounts.value);
if (status === AuthenticationStatus.LoggedOut) {
this.logout.next(userId);
} else if (status === AuthenticationStatus.Locked) {
this.lock.next(userId);
}
}
switchAccount(userId: UserId) {
if (this.accounts.value[userId] != null) {
throw new Error("Account does not exist");
}
}
// TODO: update to use our own account status settings.
async delete(): Promise<void> {
try {
this.messagingService.send("logout");

View File

@ -0,0 +1,73 @@
import { BehaviorSubject, filter, Subject } from "rxjs";
import { InternalAccountService } from "../../abstractions/account/account.service";
import { LogService } from "../../abstractions/log.service";
import { MessagingService } from "../../abstractions/messaging.service";
import { AuthenticationStatus } from "../../enums/authenticationStatus";
export class AccountServiceImplementation implements InternalAccountService {
private accounts = new BehaviorSubject<Map<string, AuthenticationStatus>>(new Map());
private activeAccount = new BehaviorSubject<{
id: string | undefined;
status: AuthenticationStatus | undefined;
}>({ id: undefined, status: undefined });
private lock = new Subject<string>();
private logout = new Subject<string>();
private unlock = new Subject<string>();
accounts$ = this.accounts.asObservable();
activeAccount$ = this.activeAccount.asObservable();
accountLocked$ = this.lock.asObservable();
accountLogout$ = this.logout.asObservable();
accountUnlocked$ = this.unlock.asObservable();
activeAccountLocked$ = this.accountLocked$.pipe(
filter((userId) => userId === this.activeAccount.value.id)
);
activeAccountUnlocked$ = this.accountUnlocked$.pipe(
filter((userId) => userId === this.activeAccount.value.id)
);
activeAccountLogout$ = this.accountLogout$.pipe(
filter((userId) => userId === this.activeAccount.value.id)
);
constructor(private messagingService: MessagingService, private logService: LogService) {}
setAccountStatus(userId: string, status: AuthenticationStatus) {
this.accounts.value.set(userId, status);
this.accounts.next(this.accounts.value);
if (status === AuthenticationStatus.LoggedOut) {
this.logout.next(userId);
} else if (status === AuthenticationStatus.Locked) {
this.lock.next(userId);
} else if (status === AuthenticationStatus.Unlocked) {
this.unlock.next(userId);
}
}
switchAccount(userId: string) {
if (!this.accounts.value.has(userId)) {
throw new Error("Account does not exist");
}
this.activeAccount.next({ id: userId, status: this.accounts.value.get(userId) });
}
delete(): void {
try {
this.logout.next(this.activeAccount.value.id);
this.accounts.value.delete(this.activeAccount.value.id);
this.accounts.next(this.accounts.value);
this.messagingService.send("logout");
} catch (e) {
this.logService.error(e);
throw e;
}
}
complete() {
this.accounts.complete();
this.activeAccount.complete();
this.lock.complete();
this.logout.complete();
}
}

5
libs/common/src/types/guid.d.ts vendored Normal file
View File

@ -0,0 +1,5 @@
import { Opaque } from "type-fest";
type Guid = Opaque<string, "Guid">;
type UserId = Opaque<string, "UserId">;