add auth status to auth service (#8377)

* add auth status to auth service

* fix auth service factory
This commit is contained in:
Jake Fink 2024-03-26 09:56:20 -04:00 committed by GitHub
parent d000f081da
commit a46767dee2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 88 additions and 3 deletions

View File

@ -23,9 +23,12 @@ import {
stateServiceFactory,
} from "../../../platform/background/service-factories/state-service.factory";
import { AccountServiceInitOptions, accountServiceFactory } from "./account-service.factory";
type AuthServiceFactoryOptions = FactoryOptions;
export type AuthServiceInitOptions = AuthServiceFactoryOptions &
AccountServiceInitOptions &
MessagingServiceInitOptions &
CryptoServiceInitOptions &
ApiServiceInitOptions &
@ -41,6 +44,7 @@ export function authServiceFactory(
opts,
async () =>
new AuthService(
await accountServiceFactory(cache, opts),
await messagingServiceFactory(cache, opts),
await cryptoServiceFactory(cache, opts),
await apiServiceFactory(cache, opts),

View File

@ -568,6 +568,7 @@ export default class MainBackground {
);
this.authService = new AuthService(
this.accountService,
backgroundMessagingService,
this.cryptoService,
this.apiService,

View File

@ -494,6 +494,7 @@ export class Main {
);
this.authService = new AuthService(
this.accountService,
this.messagingService,
this.cryptoService,
this.apiService,

View File

@ -345,6 +345,7 @@ const typesafeProviders: Array<SafeProvider> = [
provide: AuthServiceAbstraction,
useClass: AuthService,
deps: [
AccountServiceAbstraction,
MessagingServiceAbstraction,
CryptoServiceAbstraction,
ApiServiceAbstraction,

View File

@ -1,6 +1,11 @@
import { Observable } from "rxjs";
import { AuthenticationStatus } from "../enums/authentication-status";
export abstract class AuthService {
getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
logOut: (callback: () => void) => void;
/** Authentication status for the active user */
abstract activeAccountStatus$: Observable<AuthenticationStatus>;
/** @deprecated use {@link activeAccountStatus$} instead */
abstract getAuthStatus: (userId?: string) => Promise<AuthenticationStatus>;
abstract logOut: (callback: () => void) => void;
}

View File

@ -0,0 +1,61 @@
import { MockProxy, mock } from "jest-mock-extended";
import { firstValueFrom } from "rxjs";
import { FakeAccountService, mockAccountServiceWith } from "../../../spec";
import { ApiService } from "../../abstractions/api.service";
import { CryptoService } from "../../platform/abstractions/crypto.service";
import { MessagingService } from "../../platform/abstractions/messaging.service";
import { StateService } from "../../platform/abstractions/state.service";
import { Utils } from "../../platform/misc/utils";
import { UserId } from "../../types/guid";
import { AuthenticationStatus } from "../enums/authentication-status";
import { AuthService } from "./auth.service";
describe("AuthService", () => {
let sut: AuthService;
let accountService: FakeAccountService;
let messagingService: MockProxy<MessagingService>;
let cryptoService: MockProxy<CryptoService>;
let apiService: MockProxy<ApiService>;
let stateService: MockProxy<StateService>;
const userId = Utils.newGuid() as UserId;
beforeEach(() => {
accountService = mockAccountServiceWith(userId);
messagingService = mock<MessagingService>();
cryptoService = mock<CryptoService>();
apiService = mock<ApiService>();
stateService = mock<StateService>();
sut = new AuthService(
accountService,
messagingService,
cryptoService,
apiService,
stateService,
);
});
describe("activeAccountStatus$", () => {
test.each([
AuthenticationStatus.LoggedOut,
AuthenticationStatus.Locked,
AuthenticationStatus.Unlocked,
])(
`should emit %p when activeAccount$ emits an account with %p auth status`,
async (status) => {
accountService.activeAccountSubject.next({
id: userId,
email: "email",
name: "name",
status,
});
expect(await firstValueFrom(sut.activeAccountStatus$)).toEqual(status);
},
);
});
});

View File

@ -1,18 +1,30 @@
import { Observable, distinctUntilChanged, map, shareReplay } from "rxjs";
import { ApiService } from "../../abstractions/api.service";
import { CryptoService } from "../../platform/abstractions/crypto.service";
import { MessagingService } from "../../platform/abstractions/messaging.service";
import { StateService } from "../../platform/abstractions/state.service";
import { KeySuffixOptions } from "../../platform/enums";
import { AccountService } from "../abstractions/account.service";
import { AuthService as AuthServiceAbstraction } from "../abstractions/auth.service";
import { AuthenticationStatus } from "../enums/authentication-status";
export class AuthService implements AuthServiceAbstraction {
activeAccountStatus$: Observable<AuthenticationStatus>;
constructor(
protected accountService: AccountService,
protected messagingService: MessagingService,
protected cryptoService: CryptoService,
protected apiService: ApiService,
protected stateService: StateService,
) {}
) {
this.activeAccountStatus$ = this.accountService.activeAccount$.pipe(
map((account) => account.status),
distinctUntilChanged(),
shareReplay({ bufferSize: 1, refCount: false }),
);
}
async getAuthStatus(userId?: string): Promise<AuthenticationStatus> {
// If we don't have an access token or userId, we're logged out